Backtesting - Incorrect TP / SL calculation
Backtesting - Incorrect TP / SL calculation
31 Aug 2024, 05:01
Hi I have backtested my cbot and when looking up the trading history it shows different results in Pip - Take Profit
I set up a 5 TP but it almost always jumps 4-7 pips over the setup in my Parameter.
This gives an incorrect result in profits.
Is it possible to get exact, or at least more realistic, values for TP / SL?
Thank you
Replies
PanagiotisCharalampous
01 Sep 2024, 05:29
Hi there,
Please share your cBot code and make sure you are using tick data for your backtests.
Best regards,
Panagiotis
@PanagiotisCharalampous
zytotoxiziteat
01 Sep 2024, 06:11
RE: Backtesting - Incorrect TP / SL calculation
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);
}
}
}
@zytotoxiziteat
zytotoxiziteat
01 Sep 2024, 06:29
RE: RE: Backtesting - Incorrect TP / SL calculation
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); } }}
@zytotoxiziteat
zytotoxiziteat
01 Sep 2024, 06:32
( Updated at: 01 Sep 2024, 06:38 )
RE: RE: RE: Backtesting - Incorrect TP / SL calculation
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
@zytotoxiziteat
PanagiotisCharalampous
02 Sep 2024, 05:30
RE: RE: RE: RE: Backtesting - Incorrect TP / SL calculation
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 backtestingand 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
@PanagiotisCharalampous
zytotoxiziteat
02 Sep 2024, 07:25
RE: RE: RE: RE: RE: Backtesting - Incorrect TP / SL calculation
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 backtestingand I was considering to change “protected override void OnTick()” to "protected override void OnBar()".
Is that wrong?
What is the best solution?
Thank youHi 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.
@zytotoxiziteat
PanagiotisCharalampous
02 Sep 2024, 08:13
RE: RE: RE: RE: RE: RE: Backtesting - Incorrect TP / SL calculation
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 backtestingand I was considering to change “protected override void OnTick()” to "protected override void OnBar()".
Is that wrong?
What is the best solution?
Thank youHi 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.
@PanagiotisCharalampous
zytotoxiziteat
02 Sep 2024, 10:08
RE: RE: RE: RE: RE: RE: RE: Backtesting - Incorrect TP / SL calculation
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 backtestingand I was considering to change “protected override void OnTick()” to "protected override void OnBar()".
Is that wrong?
What is the best solution?
Thank youHi 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.
@zytotoxiziteat
zytotoxiziteat
02 Sep 2024, 10:09
RE: RE: RE: RE: RE: RE: RE: Backtesting - Incorrect TP / SL calculation
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 backtestingand I was considering to change “protected override void OnTick()” to "protected override void OnBar()".
Is that wrong?
What is the best solution?
Thank youHi 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.
@zytotoxiziteat
PanagiotisCharalampous
03 Sep 2024, 05:23
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:
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 backtestingand I was considering to change “protected override void OnTick()” to "protected override void OnBar()".
Is that wrong?
What is the best solution?
Thank youHi 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
@PanagiotisCharalampous
zytotoxiziteat
03 Sep 2024, 13:45
RE: RE: RE: RE: RE: RE: RE: RE: RE: Backtesting - Incorrect TP / SL calculation
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 backtestingand I was considering to change “protected override void OnTick()” to "protected override void OnBar()".
Is that wrong?
What is the best solution?
Thank youHi 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?
@zytotoxiziteat
zytotoxiziteat
03 Sep 2024, 13:46
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:
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 backtestingand I was considering to change “protected override void OnTick()” to "protected override void OnBar()".
Is that wrong?
What is the best solution?
Thank youHi 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 makes no sense to me.
@zytotoxiziteat
zytotoxiziteat
03 Sep 2024, 13:47
RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: Backtesting - Incorrect TP / SL calculation
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 backtestingand I was considering to change “protected override void OnTick()” to "protected override void OnBar()".
Is that wrong?
What is the best solution?
Thank youHi 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.
@zytotoxiziteat
PanagiotisCharalampous
04 Sep 2024, 05:26
RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: Backtesting - Incorrect TP / SL calculation
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 backtestingand I was considering to change “protected override void OnTick()” to "protected override void OnBar()".
Is that wrong?
What is the best solution?
Thank youHi 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
@PanagiotisCharalampous
zytotoxiziteat
06 Sep 2024, 17:14
( Updated at: 08 Sep 2024, 15:02 )
RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: Backtesting - Incorrect TP / SL calculation
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 backtestingand I was considering to change “protected override void OnTick()” to "protected override void OnBar()".
Is that wrong?
What is the best solution?
Thank youHi 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.
@zytotoxiziteat
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 backtestingand I was considering to change “protected override void OnTick()” to "protected override void OnBar()".
Is that wrong?
What is the best solution?
Thank youHi 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
zytotoxiziteat
09 Sep 2024, 11:03
( Updated at: 09 Sep 2024, 12:24 )
RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: Backtesting - Incorrect TP / SL calculation
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 backtestingand I was considering to change “protected override void OnTick()” to "protected override void OnBar()".
Is that wrong?
What is the best solution?
Thank youHi 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”
@zytotoxiziteat
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 backtestingand I was considering to change “protected override void OnTick()” to "protected override void OnBar()".
Is that wrong?
What is the best solution?
Thank youHi 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/JbtHJixXfPjaotherwise 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
zytotoxiziteat
09 Sep 2024, 14:35
( Updated at: 10 Sep 2024, 05:12 )
RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: Backtesting - Incorrect TP / SL calculation
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 backtestingand I was considering to change “protected override void OnTick()” to "protected override void OnBar()".
Is that wrong?
What is the best solution?
Thank youHi 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/JbtHJixXfPjaotherwise 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
@zytotoxiziteat
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 backtestingand I was considering to change “protected override void OnTick()” to "protected override void OnBar()".
Is that wrong?
What is the best solution?
Thank youHi 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/JbtHJixXfPjaotherwise 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
zytotoxiziteat
10 Sep 2024, 05:56
( Updated at: 10 Sep 2024, 05:57 )
RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: Backtesting - Incorrect TP / SL calculation
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 backtestingand I was considering to change “protected override void OnTick()” to "protected override void OnBar()".
Is that wrong?
What is the best solution?
Thank youHi 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/JbtHJixXfPjaotherwise 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/JbtHJixXfPjaI 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.
@zytotoxiziteat
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 backtestingand I was considering to change “protected override void OnTick()” to "protected override void OnBar()".
Is that wrong?
What is the best solution?
Thank youHi 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/JbtHJixXfPjaotherwise 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/JbtHJixXfPjaI 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
zytotoxiziteat
31 Aug 2024, 13:02 ( Updated at: 31 Aug 2024, 13:03 )
After retesting and sorting the values by pips I received this:
>>>160<<< Pips Take Profit ?!?!!?
How can ctrader take 160 pips profit when the parameter is clearly set on 3 ????
Can anyone explain this to me please?!
@zytotoxiziteat