PanagiotisCharalampous's avatar
PanagiotisCharalampous
26 follower(s) 0 following 1006 subscription(s)
Replies

PanagiotisCharalampous
10 Sep 2024, 07:28

RE: RE: RE: RE: Timeline for future parity of the Mac version with the Windows version?

Nicolinux said: 

PanagiotisCharalampous said: 

[…]

Hi Stefan,

  1. It will be added in 5.2 
  2. We do not have plans yet
  3. Can you please elaborate with examples?

Best regards,

Panagiotis

Regarding 1. 🎉🎉🎉

Regarding 2. Any way to influence it? Money, cookies, anything else? :)

Regarding 3. Apparently my media was not uploaded correctly. Here is what I mean. The layout of the mac version is fixed, in windows the layout is flexible.

Hi Stefan,

Free chart mode will be added but we do not have an ETA at the moment. It's not included in the next couple of updates.

Best regards,

Panagiotis


@PanagiotisCharalampous

PanagiotisCharalampous
10 Sep 2024, 05:59

RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: Backtesting - Incorrect TP / SL calculation

zytotoxiziteat said: 

PanagiotisCharalampous said: 

zytotoxiziteat said: 

PanagiotisCharalampous said: 

zytotoxiziteat said: 

 

 

PanagiotisCharalampous said: 

zytotoxiziteat said: 

 

PanagiotisCharalampous said: 

zytotoxiziteat said: 

zytotoxiziteat said: 

zytotoxiziteat said: 

PanagiotisCharalampous said: 

zytotoxiziteat said: 

PanagiotisCharalampous said: 

zytotoxiziteat said: 

PanagiotisCharalampous said: 

zytotoxiziteat said: 

zytotoxiziteat said: 

zytotoxiziteat said: 

PanagiotisCharalampous said: 

Hi there,

Please share your cBot code and make sure you are using tick data for your backtests.

Best regards,

Panagiotis

using System;using System.Collections.Generic;using cAlgo.API;using cAlgo.API.Indicators;using cAlgo.API.Internals;namespace cAlgo.Robots{    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]    public class TradingBot : Robot    {        [Parameter("Risk Percentage", DefaultValue = 1, MinValue = 0.1, MaxValue = 10)]        public double RiskPercentage { get; set; }        [Parameter("Stop Loss (Pips)", DefaultValue = 40, MinValue = 0, MaxValue = 100)]        public double StopLossPips { get; set; }        [Parameter("Take Profit (Pips)", DefaultValue = 20, MinValue = 0, MaxValue = 200)]        public double TakeProfitPips { get; set; }        private AI_101.ML101.ModelInput _modelInput;        private double _lastPrediction;        protected override void OnStart()        {            _modelInput = new AI_101.ML101.ModelInput();        }        protected override void OnTick()        {            // Ensure only one open position per currency pair            if (Positions.FindAll("ML Prediction", Symbol.Name).Length > 0)                return;            // Update model input with the latest close price            _modelInput.ClosePrice = (float)Symbol.Bid;  // Use Symbol.Bid instead of Symbol.LastTick.Bid            // Get prediction            var prediction = AI_101.ML101.Predict(_modelInput);            // Calculate the predicted price change            double predictedChange = prediction.ClosePrice[0] - _modelInput.ClosePrice;            // Determine if we should open a position            if (Math.Abs(predictedChange) > Symbol.PipSize)            {                if (predictedChange > 0 && _lastPrediction <= 0)                {                    OpenPosition(TradeType.Buy);                }                else if (predictedChange < 0 && _lastPrediction >= 0)                {                    OpenPosition(TradeType.Sell);                }            }            _lastPrediction = predictedChange;        }        private void OpenPosition(TradeType tradeType)        {            // Calculate position size based on risk            double riskAmount = Account.Balance * (RiskPercentage / 100);            double volumeInUnits = riskAmount / (StopLossPips * Symbol.PipValue);            // Ensure volume is within acceptable range and increments            volumeInUnits = Symbol.NormalizeVolumeInUnits(volumeInUnits, RoundingMode.ToNearest);            // Check if the volume is valid            if (volumeInUnits < Symbol.VolumeInUnitsMin || volumeInUnits > Symbol.VolumeInUnitsMax)            {                Print("Volume is out of range: " + volumeInUnits);                return;            }            // Open the position            ExecuteMarketOrder(tradeType, Symbol.Name, volumeInUnits, "ML Prediction", StopLossPips, TakeProfitPips);        }    }}

My thought was:

Since I collected only m5 candle data for my Machine learning module I changed the “Data” in settings to “m5 bars from server” for backtesting 

and I was considering to change “protected override void OnTick()” to "protected override void OnBar()".
 

Is that wrong?

What is the best solution?

Thank you

Hi there, 

If you are using fixed SL and TP, you need to use tick data to ensure accurate results in backtesting.

Best regards,

Panagiotis

Okay, my cbot code uses

protected override void OnTick()

I still get wrong TP.

You need to use tick data on your backtesting settings. OnTick() is irrelevant.

 

Where does the option “m5 bars from server” come from?

 

 I thought the system provided the best possible set-up because of my csv file, which contains only m5 bars data. 

 

I don't understand what you mean. It's just an option in a dropdown list

My friend,

I created a csv file with m5 bars only to train my module. I thought that is why I the option “M5” is available.

Can you please explain why in any of the options in Backtesting drop-down list is not triggering my predefined TP or SL . 

What is the point of predefining it?

I thought the Backtesting process should prepare for the real environment. But when there are options which are not correctly executed by the system makes no sense to me.

 

The options have nothing to do with the data you used to generate the model. The backtesting module has no clue what your cBot is doing. Those options are there to choose the data source to be used for the backtesting. If you don't use tick data but you use SP and TP at specific price levels, your execution will be inaccurate, since m5 bars data source only uses open prices for the execution 

Hi, ok I tried the optimizer with tick data from server.
 
The Optimizers choice of parameters : SL = 82; TP = 20

 

 

And this was the result. Again the TP was not correct: way more than 20 pips TP

 

I dont know mate. It seems to me there is no point of “testing” if the system doesnt TP/SL properly.

Hi there,

I cannot provide an explanation of what you are looking at since I do not have your cBot's code. If you can help me reproduce what you are looking at, I will explain what happens. But I am 100% sure that this is not related with inaccurate executions. I am using cTrader for the last 8 years, I backtest several cBots every day and I can confirm that the execution with tick data is exact.

Best regards,

Panagiotis

 

Bot Code:

using System;using System.Collections.Generic;using cAlgo.API;using cAlgo.API.Indicators;using cAlgo.API.Internals;namespace cAlgo.Robots{    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]    public class TradingBot : Robot    {        [Parameter("Risk Percentage", DefaultValue = 1, MinValue = 0.1, MaxValue = 20)]        public double RiskPercentage { get; set; }        [Parameter("Stop Loss (Pips)", DefaultValue = 40, MinValue = 0, MaxValue = 100)]        public double StopLossPips { get; set; }        [Parameter("Take Profit (Pips)", DefaultValue = 20, MinValue = 0, MaxValue = 200)]        public double TakeProfitPips { get; set; }        private AI_101.ML101.ModelInput _modelInput;        private double _lastPrediction;        protected override void OnStart()        {            _modelInput = new AI_101.ML101.ModelInput();        }        protected override void OnTick()        {            // Ensure only one open position per currency pair            if (Positions.FindAll("ML Prediction", Symbol.Name).Length > 0)                return;            // Update model input with the latest close price            _modelInput.ClosePrice = (float)Symbol.Bid;  // Use Symbol.Bid instead of Symbol.LastTick.Bid            // Get prediction            var prediction = AI_101.ML101.Predict(_modelInput);            // Calculate the predicted price change            double predictedChange = prediction.ClosePrice[0] - _modelInput.ClosePrice;            // Determine if we should open a position            if (Math.Abs(predictedChange) > Symbol.PipSize)            {                if (predictedChange > 0 && _lastPrediction <= 0)                {                    OpenPosition(TradeType.Buy);                }                else if (predictedChange < 0 && _lastPrediction >= 0)                {                    OpenPosition(TradeType.Sell);                }            }            _lastPrediction = predictedChange;        }        private void OpenPosition(TradeType tradeType)        {            // Calculate position size based on risk            double riskAmount = Account.Balance * (RiskPercentage / 100);            double volumeInUnits = riskAmount / (StopLossPips * Symbol.PipValue);            // Ensure volume is within acceptable range and increments            volumeInUnits = Symbol.NormalizeVolumeInUnits(volumeInUnits, RoundingMode.ToNearest);            // Check if the volume is valid            if (volumeInUnits < Symbol.VolumeInUnitsMin || volumeInUnits > Symbol.VolumeInUnitsMax)            {                Print("Volume is out of range: " + volumeInUnits);                return;            }            // Open the position            ExecuteMarketOrder(tradeType, Symbol.Name, volumeInUnits, "ML Prediction", StopLossPips, TakeProfitPips);        }    }}

 

I tried to optimize AUD/USD this time.
Here is a link to my .optres file: https://file.io/JbtHJixXfPja

otherwise here is a documentation of “Report”, "Events" and “Paramaters” of my optimizer:

 

 

As you can see I used tick data, the parameters are set to SL/TP= 69/90 which are not met if I sort it by “Pips”

Unfortunately I cannot run your code without this part

            _modelInput = new AI_101.ML101.ModelInput();

If you can reproduce the issue without this line of code, I am more than happy to have a look

This is the link to the Ai#101 Module and my csv file:

https://file.io/JbtHJixXfPja

I am not able to open this. In any case, if there is an issue with cTrader, this module is irrelevant. You would be able to reproduce it without it

I am not sure what you mean with reproducing?

I used it on my local machine and on an other virtual machine. In both cases I had the same wrong SL/TP results. 

 

 

I mean that this should happen on other cBots as well. If you are able to provide a cBot and parameters that we can run, I will explain to you what happens. At the moment I cannot reproduce such behavior


@PanagiotisCharalampous

PanagiotisCharalampous
10 Sep 2024, 05:17

Hi there,

We do not plan to support this feature at the moment.

Best regards,

Panagiotis


@PanagiotisCharalampous

PanagiotisCharalampous
10 Sep 2024, 05:15

RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: Backtesting - Incorrect TP / SL calculation

zytotoxiziteat said: 

PanagiotisCharalampous said: 

zytotoxiziteat said: 

 

 

PanagiotisCharalampous said: 

zytotoxiziteat said: 

 

PanagiotisCharalampous said: 

zytotoxiziteat said: 

zytotoxiziteat said: 

zytotoxiziteat said: 

PanagiotisCharalampous said: 

zytotoxiziteat said: 

PanagiotisCharalampous said: 

zytotoxiziteat said: 

PanagiotisCharalampous said: 

zytotoxiziteat said: 

zytotoxiziteat said: 

zytotoxiziteat said: 

PanagiotisCharalampous said: 

Hi there,

Please share your cBot code and make sure you are using tick data for your backtests.

Best regards,

Panagiotis

using System;using System.Collections.Generic;using cAlgo.API;using cAlgo.API.Indicators;using cAlgo.API.Internals;namespace cAlgo.Robots{    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]    public class TradingBot : Robot    {        [Parameter("Risk Percentage", DefaultValue = 1, MinValue = 0.1, MaxValue = 10)]        public double RiskPercentage { get; set; }        [Parameter("Stop Loss (Pips)", DefaultValue = 40, MinValue = 0, MaxValue = 100)]        public double StopLossPips { get; set; }        [Parameter("Take Profit (Pips)", DefaultValue = 20, MinValue = 0, MaxValue = 200)]        public double TakeProfitPips { get; set; }        private AI_101.ML101.ModelInput _modelInput;        private double _lastPrediction;        protected override void OnStart()        {            _modelInput = new AI_101.ML101.ModelInput();        }        protected override void OnTick()        {            // Ensure only one open position per currency pair            if (Positions.FindAll("ML Prediction", Symbol.Name).Length > 0)                return;            // Update model input with the latest close price            _modelInput.ClosePrice = (float)Symbol.Bid;  // Use Symbol.Bid instead of Symbol.LastTick.Bid            // Get prediction            var prediction = AI_101.ML101.Predict(_modelInput);            // Calculate the predicted price change            double predictedChange = prediction.ClosePrice[0] - _modelInput.ClosePrice;            // Determine if we should open a position            if (Math.Abs(predictedChange) > Symbol.PipSize)            {                if (predictedChange > 0 && _lastPrediction <= 0)                {                    OpenPosition(TradeType.Buy);                }                else if (predictedChange < 0 && _lastPrediction >= 0)                {                    OpenPosition(TradeType.Sell);                }            }            _lastPrediction = predictedChange;        }        private void OpenPosition(TradeType tradeType)        {            // Calculate position size based on risk            double riskAmount = Account.Balance * (RiskPercentage / 100);            double volumeInUnits = riskAmount / (StopLossPips * Symbol.PipValue);            // Ensure volume is within acceptable range and increments            volumeInUnits = Symbol.NormalizeVolumeInUnits(volumeInUnits, RoundingMode.ToNearest);            // Check if the volume is valid            if (volumeInUnits < Symbol.VolumeInUnitsMin || volumeInUnits > Symbol.VolumeInUnitsMax)            {                Print("Volume is out of range: " + volumeInUnits);                return;            }            // Open the position            ExecuteMarketOrder(tradeType, Symbol.Name, volumeInUnits, "ML Prediction", StopLossPips, TakeProfitPips);        }    }}

My thought was:

Since I collected only m5 candle data for my Machine learning module I changed the “Data” in settings to “m5 bars from server” for backtesting 

and I was considering to change “protected override void OnTick()” to "protected override void OnBar()".
 

Is that wrong?

What is the best solution?

Thank you

Hi there, 

If you are using fixed SL and TP, you need to use tick data to ensure accurate results in backtesting.

Best regards,

Panagiotis

Okay, my cbot code uses

protected override void OnTick()

I still get wrong TP.

You need to use tick data on your backtesting settings. OnTick() is irrelevant.

 

Where does the option “m5 bars from server” come from?

 

 I thought the system provided the best possible set-up because of my csv file, which contains only m5 bars data. 

 

I don't understand what you mean. It's just an option in a dropdown list

My friend,

I created a csv file with m5 bars only to train my module. I thought that is why I the option “M5” is available.

Can you please explain why in any of the options in Backtesting drop-down list is not triggering my predefined TP or SL . 

What is the point of predefining it?

I thought the Backtesting process should prepare for the real environment. But when there are options which are not correctly executed by the system makes no sense to me.

 

The options have nothing to do with the data you used to generate the model. The backtesting module has no clue what your cBot is doing. Those options are there to choose the data source to be used for the backtesting. If you don't use tick data but you use SP and TP at specific price levels, your execution will be inaccurate, since m5 bars data source only uses open prices for the execution 

Hi, ok I tried the optimizer with tick data from server.
 
The Optimizers choice of parameters : SL = 82; TP = 20

 

 

And this was the result. Again the TP was not correct: way more than 20 pips TP

 

I dont know mate. It seems to me there is no point of “testing” if the system doesnt TP/SL properly.

Hi there,

I cannot provide an explanation of what you are looking at since I do not have your cBot's code. If you can help me reproduce what you are looking at, I will explain what happens. But I am 100% sure that this is not related with inaccurate executions. I am using cTrader for the last 8 years, I backtest several cBots every day and I can confirm that the execution with tick data is exact.

Best regards,

Panagiotis

 

Bot Code:

using System;using System.Collections.Generic;using cAlgo.API;using cAlgo.API.Indicators;using cAlgo.API.Internals;namespace cAlgo.Robots{    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]    public class TradingBot : Robot    {        [Parameter("Risk Percentage", DefaultValue = 1, MinValue = 0.1, MaxValue = 20)]        public double RiskPercentage { get; set; }        [Parameter("Stop Loss (Pips)", DefaultValue = 40, MinValue = 0, MaxValue = 100)]        public double StopLossPips { get; set; }        [Parameter("Take Profit (Pips)", DefaultValue = 20, MinValue = 0, MaxValue = 200)]        public double TakeProfitPips { get; set; }        private AI_101.ML101.ModelInput _modelInput;        private double _lastPrediction;        protected override void OnStart()        {            _modelInput = new AI_101.ML101.ModelInput();        }        protected override void OnTick()        {            // Ensure only one open position per currency pair            if (Positions.FindAll("ML Prediction", Symbol.Name).Length > 0)                return;            // Update model input with the latest close price            _modelInput.ClosePrice = (float)Symbol.Bid;  // Use Symbol.Bid instead of Symbol.LastTick.Bid            // Get prediction            var prediction = AI_101.ML101.Predict(_modelInput);            // Calculate the predicted price change            double predictedChange = prediction.ClosePrice[0] - _modelInput.ClosePrice;            // Determine if we should open a position            if (Math.Abs(predictedChange) > Symbol.PipSize)            {                if (predictedChange > 0 && _lastPrediction <= 0)                {                    OpenPosition(TradeType.Buy);                }                else if (predictedChange < 0 && _lastPrediction >= 0)                {                    OpenPosition(TradeType.Sell);                }            }            _lastPrediction = predictedChange;        }        private void OpenPosition(TradeType tradeType)        {            // Calculate position size based on risk            double riskAmount = Account.Balance * (RiskPercentage / 100);            double volumeInUnits = riskAmount / (StopLossPips * Symbol.PipValue);            // Ensure volume is within acceptable range and increments            volumeInUnits = Symbol.NormalizeVolumeInUnits(volumeInUnits, RoundingMode.ToNearest);            // Check if the volume is valid            if (volumeInUnits < Symbol.VolumeInUnitsMin || volumeInUnits > Symbol.VolumeInUnitsMax)            {                Print("Volume is out of range: " + volumeInUnits);                return;            }            // Open the position            ExecuteMarketOrder(tradeType, Symbol.Name, volumeInUnits, "ML Prediction", StopLossPips, TakeProfitPips);        }    }}

 

I tried to optimize AUD/USD this time.
Here is a link to my .optres file: https://file.io/JbtHJixXfPja

otherwise here is a documentation of “Report”, "Events" and “Paramaters” of my optimizer:

 

 

As you can see I used tick data, the parameters are set to SL/TP= 69/90 which are not met if I sort it by “Pips”

Unfortunately I cannot run your code without this part

            _modelInput = new AI_101.ML101.ModelInput();

If you can reproduce the issue without this line of code, I am more than happy to have a look

This is the link to the Ai#101 Module and my csv file:

https://file.io/JbtHJixXfPja

I am not able to open this. In any case, if there is an issue with cTrader, this module is irrelevant. You would be able to reproduce it without it


@PanagiotisCharalampous

PanagiotisCharalampous
09 Sep 2024, 12:36

Hi Jan,

Unfortunately caching is not available. However loading time is not affected by the increment size but by the network bandwidth.

Best regards,

Panagiotis

 


@PanagiotisCharalampous

PanagiotisCharalampous
09 Sep 2024, 12:34

RE: RE: RE: Where is doc for MarketSeries price data?

martins said: 

martins said: 

PanagiotisCharalampous said: 

Hi martins,

Thanks for your suggestions but we disagree with maintaining multiple versions of documentation. Old code does not need to be maintained but needs to be updated. Obsolete methods are only supported so that developers have enough time to update their obsolete code without service interruptions. New development is not supported. Therefore we do not plan to make it easy for people not to update their code.

Best regards,

Panagiotis

OK, thank you for your replies on this. Hopefully you understand I wasn't really suggesting “maintaining” the whole old doc, as in having to review or edit it forever, I was merely suggesting either an archive area with complete as-is old doc (ie without relying on internet archive wayback), OR an easy-to-find set of migration docs, issued at the time of the change but to be considered an appendix of the current doc, on how to update from a deprecated way to a new way. Perhaps just an area with all the “what's new in release x” notes would do.

My main point was to suggest the information needed in order to comply with your assertion “Old code does not need to be maintained but needs to be updated” should be somewhere within the official current documentation, and, not only available by searching the internet or interpreting warning compile-time messages or finding old forum or blog items for items such as https://ctrader.com/forum/ctrader-blog/22440/ 

(My usage of the word “maintain” includes making changes for your “needs to be updated” so I wouldn't [pedantically] agree with “Old code does not need to be maintained”!)

More philosophically: without official information on how old code needs to be updated, there is no support for old code, which effectively means there is no real support for current code because the customer can't trust that a current feature they've used might not become old and without migration information ‘next week’.

Hi martins,

without official information on how old code needs to be updated, there is no support for old code, which effectively means there is no real support for current code because the customer can't trust that a current feature they've used might not become old and without migration information ‘next week’.

For obsolete classes and members you should get a message indicating what you should use instead. See below

 


@PanagiotisCharalampous

PanagiotisCharalampous
09 Sep 2024, 12:29

RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: Backtesting - Incorrect TP / SL calculation

zytotoxiziteat said: 

 

 

PanagiotisCharalampous said: 

zytotoxiziteat said: 

 

PanagiotisCharalampous said: 

zytotoxiziteat said: 

zytotoxiziteat said: 

zytotoxiziteat said: 

PanagiotisCharalampous said: 

zytotoxiziteat said: 

PanagiotisCharalampous said: 

zytotoxiziteat said: 

PanagiotisCharalampous said: 

zytotoxiziteat said: 

zytotoxiziteat said: 

zytotoxiziteat said: 

PanagiotisCharalampous said: 

Hi there,

Please share your cBot code and make sure you are using tick data for your backtests.

Best regards,

Panagiotis

using System;using System.Collections.Generic;using cAlgo.API;using cAlgo.API.Indicators;using cAlgo.API.Internals;namespace cAlgo.Robots{    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]    public class TradingBot : Robot    {        [Parameter("Risk Percentage", DefaultValue = 1, MinValue = 0.1, MaxValue = 10)]        public double RiskPercentage { get; set; }        [Parameter("Stop Loss (Pips)", DefaultValue = 40, MinValue = 0, MaxValue = 100)]        public double StopLossPips { get; set; }        [Parameter("Take Profit (Pips)", DefaultValue = 20, MinValue = 0, MaxValue = 200)]        public double TakeProfitPips { get; set; }        private AI_101.ML101.ModelInput _modelInput;        private double _lastPrediction;        protected override void OnStart()        {            _modelInput = new AI_101.ML101.ModelInput();        }        protected override void OnTick()        {            // Ensure only one open position per currency pair            if (Positions.FindAll("ML Prediction", Symbol.Name).Length > 0)                return;            // Update model input with the latest close price            _modelInput.ClosePrice = (float)Symbol.Bid;  // Use Symbol.Bid instead of Symbol.LastTick.Bid            // Get prediction            var prediction = AI_101.ML101.Predict(_modelInput);            // Calculate the predicted price change            double predictedChange = prediction.ClosePrice[0] - _modelInput.ClosePrice;            // Determine if we should open a position            if (Math.Abs(predictedChange) > Symbol.PipSize)            {                if (predictedChange > 0 && _lastPrediction <= 0)                {                    OpenPosition(TradeType.Buy);                }                else if (predictedChange < 0 && _lastPrediction >= 0)                {                    OpenPosition(TradeType.Sell);                }            }            _lastPrediction = predictedChange;        }        private void OpenPosition(TradeType tradeType)        {            // Calculate position size based on risk            double riskAmount = Account.Balance * (RiskPercentage / 100);            double volumeInUnits = riskAmount / (StopLossPips * Symbol.PipValue);            // Ensure volume is within acceptable range and increments            volumeInUnits = Symbol.NormalizeVolumeInUnits(volumeInUnits, RoundingMode.ToNearest);            // Check if the volume is valid            if (volumeInUnits < Symbol.VolumeInUnitsMin || volumeInUnits > Symbol.VolumeInUnitsMax)            {                Print("Volume is out of range: " + volumeInUnits);                return;            }            // Open the position            ExecuteMarketOrder(tradeType, Symbol.Name, volumeInUnits, "ML Prediction", StopLossPips, TakeProfitPips);        }    }}

My thought was:

Since I collected only m5 candle data for my Machine learning module I changed the “Data” in settings to “m5 bars from server” for backtesting 

and I was considering to change “protected override void OnTick()” to "protected override void OnBar()".
 

Is that wrong?

What is the best solution?

Thank you

Hi there, 

If you are using fixed SL and TP, you need to use tick data to ensure accurate results in backtesting.

Best regards,

Panagiotis

Okay, my cbot code uses

protected override void OnTick()

I still get wrong TP.

You need to use tick data on your backtesting settings. OnTick() is irrelevant.

 

Where does the option “m5 bars from server” come from?

 

 I thought the system provided the best possible set-up because of my csv file, which contains only m5 bars data. 

 

I don't understand what you mean. It's just an option in a dropdown list

My friend,

I created a csv file with m5 bars only to train my module. I thought that is why I the option “M5” is available.

Can you please explain why in any of the options in Backtesting drop-down list is not triggering my predefined TP or SL . 

What is the point of predefining it?

I thought the Backtesting process should prepare for the real environment. But when there are options which are not correctly executed by the system makes no sense to me.

 

The options have nothing to do with the data you used to generate the model. The backtesting module has no clue what your cBot is doing. Those options are there to choose the data source to be used for the backtesting. If you don't use tick data but you use SP and TP at specific price levels, your execution will be inaccurate, since m5 bars data source only uses open prices for the execution 

Hi, ok I tried the optimizer with tick data from server.
 
The Optimizers choice of parameters : SL = 82; TP = 20

 

 

And this was the result. Again the TP was not correct: way more than 20 pips TP

 

I dont know mate. It seems to me there is no point of “testing” if the system doesnt TP/SL properly.

Hi there,

I cannot provide an explanation of what you are looking at since I do not have your cBot's code. If you can help me reproduce what you are looking at, I will explain what happens. But I am 100% sure that this is not related with inaccurate executions. I am using cTrader for the last 8 years, I backtest several cBots every day and I can confirm that the execution with tick data is exact.

Best regards,

Panagiotis

 

Bot Code:

using System;using System.Collections.Generic;using cAlgo.API;using cAlgo.API.Indicators;using cAlgo.API.Internals;namespace cAlgo.Robots{    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]    public class TradingBot : Robot    {        [Parameter("Risk Percentage", DefaultValue = 1, MinValue = 0.1, MaxValue = 20)]        public double RiskPercentage { get; set; }        [Parameter("Stop Loss (Pips)", DefaultValue = 40, MinValue = 0, MaxValue = 100)]        public double StopLossPips { get; set; }        [Parameter("Take Profit (Pips)", DefaultValue = 20, MinValue = 0, MaxValue = 200)]        public double TakeProfitPips { get; set; }        private AI_101.ML101.ModelInput _modelInput;        private double _lastPrediction;        protected override void OnStart()        {            _modelInput = new AI_101.ML101.ModelInput();        }        protected override void OnTick()        {            // Ensure only one open position per currency pair            if (Positions.FindAll("ML Prediction", Symbol.Name).Length > 0)                return;            // Update model input with the latest close price            _modelInput.ClosePrice = (float)Symbol.Bid;  // Use Symbol.Bid instead of Symbol.LastTick.Bid            // Get prediction            var prediction = AI_101.ML101.Predict(_modelInput);            // Calculate the predicted price change            double predictedChange = prediction.ClosePrice[0] - _modelInput.ClosePrice;            // Determine if we should open a position            if (Math.Abs(predictedChange) > Symbol.PipSize)            {                if (predictedChange > 0 && _lastPrediction <= 0)                {                    OpenPosition(TradeType.Buy);                }                else if (predictedChange < 0 && _lastPrediction >= 0)                {                    OpenPosition(TradeType.Sell);                }            }            _lastPrediction = predictedChange;        }        private void OpenPosition(TradeType tradeType)        {            // Calculate position size based on risk            double riskAmount = Account.Balance * (RiskPercentage / 100);            double volumeInUnits = riskAmount / (StopLossPips * Symbol.PipValue);            // Ensure volume is within acceptable range and increments            volumeInUnits = Symbol.NormalizeVolumeInUnits(volumeInUnits, RoundingMode.ToNearest);            // Check if the volume is valid            if (volumeInUnits < Symbol.VolumeInUnitsMin || volumeInUnits > Symbol.VolumeInUnitsMax)            {                Print("Volume is out of range: " + volumeInUnits);                return;            }            // Open the position            ExecuteMarketOrder(tradeType, Symbol.Name, volumeInUnits, "ML Prediction", StopLossPips, TakeProfitPips);        }    }}

 

I tried to optimize AUD/USD this time.
Here is a link to my .optres file: https://file.io/JbtHJixXfPja

otherwise here is a documentation of “Report”, "Events" and “Paramaters” of my optimizer:

 

 

As you can see I used tick data, the parameters are set to SL/TP= 69/90 which are not met if I sort it by “Pips”

Unfortunately I cannot run your code without this part

            _modelInput = new AI_101.ML101.ModelInput();

If you can reproduce the issue without this line of code, I am more than happy to have a look


@PanagiotisCharalampous

PanagiotisCharalampous
09 Sep 2024, 09:32

RE: RE: Timeline for future parity of the Mac version with the Windows version?

Nicolinux said: 

PanagiotisCharalampous said: 

Hi Steve,

This is not expected to happen anytime soon. While the Mac team is catching up, the Windows team is developing new features. So there will be differences at least for the foreseeable future.

Best regards,

Panagiotis

Hi Panagiotis,

thanks for the answer. Might I ask about a few specific features? There is not much that's missing on the Mac version:

  1. History Tab, realised $. This is missing on the Mac, and seems like a pretty easy feature to add.

 

2. Pending orders via drag-out thingie. This is missing on the Mac and super useful in the Windows version

 

3. Flexible Layout. This is also missing on the Mac and makes the interface harder to use because one can not resize

 

Thanks & best wishes,

Stefan

Hi Stefan,

  1. It will be added in 5.2 
  2. We do not have plans yet
  3. Can you please elaborate with examples?

Best regards,

Panagiotis


@PanagiotisCharalampous

PanagiotisCharalampous
09 Sep 2024, 06:34

Hi there,

You should talk to your broker regarding withdrawals.

Best regards,

Panagiotis


@PanagiotisCharalampous

PanagiotisCharalampous
09 Sep 2024, 06:32

Hi there,

You can use the MouseDown event to achieve this.

Best regards,

Panagiotis


@PanagiotisCharalampous

PanagiotisCharalampous
09 Sep 2024, 06:28

Hi there,

No, this option is not available at the moment on cTrader for Mac.

Best regards,

Panagiotis


@PanagiotisCharalampous

PanagiotisCharalampous
09 Sep 2024, 06:22

Hi martins,

Thanks for your suggestions but we disagree with maintaining multiple versions of documentation. Old code does not need to be maintained but needs to be updated. Obsolete methods are only supported so that developers have enough time to update their obsolete code without service interruptions. New development is not supported. Therefore we do not plan to make it easy for people not to update their code.

Best regards,

Panagiotis


@PanagiotisCharalampous

PanagiotisCharalampous
09 Sep 2024, 06:14

Hi all,

This should have been fixed now. Let us know if you still experience any issues.

Best regards,

Panagiotis


@PanagiotisCharalampous

PanagiotisCharalampous
09 Sep 2024, 06:13

Hi all,

This should have been fixed now. Let us know if you still experience any issues.

Best regards,

Panagiotis


@PanagiotisCharalampous

PanagiotisCharalampous
09 Sep 2024, 06:11

RE: RE: POOR SERVICE

firemyst said: 

PanagiotisCharalampous said: 

Hi there,

Telegram is not the place to report your issues. Your emails were not received. Your video has been forwarded to the product team for further investigation.

Best regards,

Panagiotis

@PanagiotisCharalampous:

Here's another report of your team not receiving emails people are sending to the “community” email address. 

I think this should warrant some kind of investigation on Spotware's side to see why as there's now at least 2 users who had sent emails through, but Spotware didn't receive them.

To refresh, here's the thread on an issue I reported where after sending the initial issue to the Community addresses, they didn't receive any further emails from me once I tried sending through my VPS information:

https://ctrader.com/forum/ctrader-algo/44559/#post-113028

 

 

Hi firemyst,

Thanks, we fixed the issue.

Best regards,

Panagiotis


@PanagiotisCharalampous

PanagiotisCharalampous
09 Sep 2024, 06:06

RE: RE: RE: RE: Closing part of a position in backtesting

da.weber92 said: 

firemyst said: 

da.weber92 said: 

firemyst said: 

If you wrote your own bot, then you do it in your code by modifying the position and reducing the volume of your position when your criteria are met.

Sorry for being unprecise, but I meant manual backtesting without a bot or even indicators. Just looking at the chart and using a little bit of intuition.

 

I am using hedging for some time now and you can get out of bad trades by partly closing positions quite well. But I can not do that in replay mode or I did not find the option to do this.

Just double click on your order in the order window and the modify order window comes up.

Reduce the volume of your position and click to update your order.

I tried doing that before because I know this works in live trading, but in replay mode nothing happens when I double click. I am afraid that it is just not implemented yet :/

Hi there,

Indeed this is not implemented yet.

Best regards,

Panagiotis


@PanagiotisCharalampous

PanagiotisCharalampous
09 Sep 2024, 06:02

Hi there,

Please let us know if you still experience this issue after the weekend's update.

Best regards,

Panagiotis


@PanagiotisCharalampous

PanagiotisCharalampous
09 Sep 2024, 06:00

RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: Backtesting - Incorrect TP / SL calculation

zytotoxiziteat said: 

 

PanagiotisCharalampous said: 

zytotoxiziteat said: 

zytotoxiziteat said: 

zytotoxiziteat said: 

PanagiotisCharalampous said: 

zytotoxiziteat said: 

PanagiotisCharalampous said: 

zytotoxiziteat said: 

PanagiotisCharalampous said: 

zytotoxiziteat said: 

zytotoxiziteat said: 

zytotoxiziteat said: 

PanagiotisCharalampous said: 

Hi there,

Please share your cBot code and make sure you are using tick data for your backtests.

Best regards,

Panagiotis

using System;using System.Collections.Generic;using cAlgo.API;using cAlgo.API.Indicators;using cAlgo.API.Internals;namespace cAlgo.Robots{    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]    public class TradingBot : Robot    {        [Parameter("Risk Percentage", DefaultValue = 1, MinValue = 0.1, MaxValue = 10)]        public double RiskPercentage { get; set; }        [Parameter("Stop Loss (Pips)", DefaultValue = 40, MinValue = 0, MaxValue = 100)]        public double StopLossPips { get; set; }        [Parameter("Take Profit (Pips)", DefaultValue = 20, MinValue = 0, MaxValue = 200)]        public double TakeProfitPips { get; set; }        private AI_101.ML101.ModelInput _modelInput;        private double _lastPrediction;        protected override void OnStart()        {            _modelInput = new AI_101.ML101.ModelInput();        }        protected override void OnTick()        {            // Ensure only one open position per currency pair            if (Positions.FindAll("ML Prediction", Symbol.Name).Length > 0)                return;            // Update model input with the latest close price            _modelInput.ClosePrice = (float)Symbol.Bid;  // Use Symbol.Bid instead of Symbol.LastTick.Bid            // Get prediction            var prediction = AI_101.ML101.Predict(_modelInput);            // Calculate the predicted price change            double predictedChange = prediction.ClosePrice[0] - _modelInput.ClosePrice;            // Determine if we should open a position            if (Math.Abs(predictedChange) > Symbol.PipSize)            {                if (predictedChange > 0 && _lastPrediction <= 0)                {                    OpenPosition(TradeType.Buy);                }                else if (predictedChange < 0 && _lastPrediction >= 0)                {                    OpenPosition(TradeType.Sell);                }            }            _lastPrediction = predictedChange;        }        private void OpenPosition(TradeType tradeType)        {            // Calculate position size based on risk            double riskAmount = Account.Balance * (RiskPercentage / 100);            double volumeInUnits = riskAmount / (StopLossPips * Symbol.PipValue);            // Ensure volume is within acceptable range and increments            volumeInUnits = Symbol.NormalizeVolumeInUnits(volumeInUnits, RoundingMode.ToNearest);            // Check if the volume is valid            if (volumeInUnits < Symbol.VolumeInUnitsMin || volumeInUnits > Symbol.VolumeInUnitsMax)            {                Print("Volume is out of range: " + volumeInUnits);                return;            }            // Open the position            ExecuteMarketOrder(tradeType, Symbol.Name, volumeInUnits, "ML Prediction", StopLossPips, TakeProfitPips);        }    }}

My thought was:

Since I collected only m5 candle data for my Machine learning module I changed the “Data” in settings to “m5 bars from server” for backtesting 

and I was considering to change “protected override void OnTick()” to "protected override void OnBar()".
 

Is that wrong?

What is the best solution?

Thank you

Hi there, 

If you are using fixed SL and TP, you need to use tick data to ensure accurate results in backtesting.

Best regards,

Panagiotis

Okay, my cbot code uses

protected override void OnTick()

I still get wrong TP.

You need to use tick data on your backtesting settings. OnTick() is irrelevant.

 

Where does the option “m5 bars from server” come from?

 

 I thought the system provided the best possible set-up because of my csv file, which contains only m5 bars data. 

 

I don't understand what you mean. It's just an option in a dropdown list

My friend,

I created a csv file with m5 bars only to train my module. I thought that is why I the option “M5” is available.

Can you please explain why in any of the options in Backtesting drop-down list is not triggering my predefined TP or SL . 

What is the point of predefining it?

I thought the Backtesting process should prepare for the real environment. But when there are options which are not correctly executed by the system makes no sense to me.

 

The options have nothing to do with the data you used to generate the model. The backtesting module has no clue what your cBot is doing. Those options are there to choose the data source to be used for the backtesting. If you don't use tick data but you use SP and TP at specific price levels, your execution will be inaccurate, since m5 bars data source only uses open prices for the execution 

Hi, ok I tried the optimizer with tick data from server.
 
The Optimizers choice of parameters : SL = 82; TP = 20

 

 

And this was the result. Again the TP was not correct: way more than 20 pips TP

 

I dont know mate. It seems to me there is no point of “testing” if the system doesnt TP/SL properly.

Hi there,

I cannot provide an explanation of what you are looking at since I do not have your cBot's code. If you can help me reproduce what you are looking at, I will explain what happens. But I am 100% sure that this is not related with inaccurate executions. I am using cTrader for the last 8 years, I backtest several cBots every day and I can confirm that the execution with tick data is exact.

Best regards,

Panagiotis


@PanagiotisCharalampous

PanagiotisCharalampous
09 Sep 2024, 05:53

RE: Push notifications not working

MobileTrader said: 

Hello,

I have the same issue again, I'm not receiving notification. Using ctrader crossbroker app for android.

Can you please check?

Thank you!

Hi there,

Please let me know if you still experience this issue after the weekend's update.

Best regards,

Panagiotis


@PanagiotisCharalampous

PanagiotisCharalampous
09 Sep 2024, 05:50

Hi swingfish,

You can use Open API to achieve this.

Best regards,

Panagiotis


@PanagiotisCharalampous