CBot works well when backtesting but it does not place trades when i test it on live or demo accounts.
CBot works well when backtesting but it does not place trades when i test it on live or demo accounts.
18 May 2021, 11:16
Hello, I've downloaded the night breakout bot which is available for free here. The bot is working well when backtesting in visual or non visual mod but when I test it in demo and live accounts, it doesn't place trades.
Here in the visual backtest, a trade is executed today:
But at the same time in both demo and live accounts, no trades were executed although the bot and ctrader were left active the moment a trade should've been executed.
Here is the full code:
using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;
using System.Collections.Generic;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class NightBreakoutcBot : Robot
{
// ======================================================================
[Parameter("GMT start hour", Group = "Box hours and size", DefaultValue = 22, MinValue = 0, MaxValue = 23)]
public int ParamStartHour { get; set; }
[Parameter("GMT start minute", Group = "Box hours and size", DefaultValue = 0, MinValue = 0, MaxValue = 59)]
public int ParamStartMinute { get; set; }
[Parameter("GMT end hour", Group = "Box hours and size", DefaultValue = 2, MinValue = 0, MaxValue = 23)]
public int ParamEndHour { get; set; }
[Parameter("GMT end minute", Group = "Box hours and size", DefaultValue = 0, MinValue = 0, MaxValue = 59)]
public int ParamEndMinute { get; set; }
[Parameter("Adjust summer time", Group = "Box hours and size", DefaultValue = true)]
public bool ParamAdjustSummerTime { get; set; }
[Parameter("Min box size (pips)", Group = "Box hours and size", DefaultValue = 15, MinValue = 0)]
public int ParamMinBoxHeight { get; set; }
[Parameter("Max box size (pips)", Group = "Box hours and size", DefaultValue = 45, MinValue = 0)]
public int ParamMaxBoxHeight { get; set; }
// ======================================================================
// Choose fixed lot size or risk
[Parameter("Method", Group = "Money management", DefaultValue = MMType.FIXED_LOT)]
public MMType ParamMoneyMgmntType { get; set; }
// Fixed lot size
[Parameter("Lot size", Group = "Money management", DefaultValue = 0.01, MinValue = 0.01)]
public double ParamLotSize { get; set; }
// Percent of risk
[Parameter("Risk %", Group = "Money management", DefaultValue = 2, MinValue = 0.1, MaxValue = 50.0)]
public double ParamRisk { get; set; }
// ===============================================================================
[Parameter("Draw boxes in chart", Group = "Chart", DefaultValue = true)]
public bool ParamDrawBoxes { get; set; }
private string label = "NightBreakoutcBot";
private string version = "1.0";
private Status status;
private double volume;
private double hightakeProfitPrice;
private double highStopLossPrice;
private double highEntryPrice;
private double lowtakeProfitPrice;
private double lowStopLossPrice;
private double lowEntryPrice;
protected override void OnStart()
{
try
{
Positions.Closed += onPositionClosed;
this.volume = Symbol.QuantityToVolumeInUnits(this.ParamLotSize);
if (this.ParamDrawBoxes && (this.RunningMode == RunningMode.RealTime || this.RunningMode == RunningMode.VisualBacktesting))
{
this.drawPastBoxes();
}
this.status = Status.IDLE;
this.hightakeProfitPrice = 0.0;
this.highStopLossPrice = 0.0;
this.highEntryPrice = 0.0;
this.lowtakeProfitPrice = 0.0;
this.lowStopLossPrice = 0.0;
this.lowEntryPrice = 0.0;
if (this.RunningMode == RunningMode.RealTime || this.RunningMode == RunningMode.VisualBacktesting)
{
Chart.DrawStaticText("version", "NightBreakout cBot " + this.version, VerticalAlignment.Bottom, HorizontalAlignment.Left, Chart.ColorSettings.ForegroundColor);
}
Print("Started " + this.label + " version " + this.version);
} catch (Exception exc)
{
Print(exc.Message + " " + exc.StackTrace);
throw exc;
}
}
private void drawPastBoxes()
{
int finalIndex = Bars.Count - 1;
for (int i = 30; i <= finalIndex; i++)
{
BoxHours boxHours = this.getBoxHours(Bars.OpenTimes[i]);
int firstindex = 0;
if (Bars.OpenTimes[i].Hour == boxHours.endHour && Bars.OpenTimes[i].Minute == this.ParamStartMinute)
{
for (int j = i - 1; j > 0; j--)
{
if (Bars.OpenTimes[j].Hour == boxHours.startHour && Bars.OpenTimes[j].Minute == this.ParamEndMinute)
{
firstindex = j;
break;
}
}
double high = Bars.HighPrices[firstindex];
double low = Bars.LowPrices[firstindex];
for (int k = firstindex; k <= i; k++)
{
high = Math.Max(high, Bars.HighPrices[k]);
low = Math.Min(low, Bars.LowPrices[k]);
}
double delta = high - low;
Color color = Color.Lime;
if (delta < this.ParamMinBoxHeight * Symbol.PipSize || delta > this.ParamMaxBoxHeight * Symbol.PipSize)
{
color = Color.Red;
}
Chart.DrawRectangle(Guid.NewGuid().ToString(), firstindex, high, i, low, color, 2);
Chart.DrawTrendLine(Guid.NewGuid().ToString(), i, high + delta, i + 20, high + delta, color);
Chart.DrawTrendLine(Guid.NewGuid().ToString(), i, low - delta, i + 20, low - delta, color);
}
}
}
protected override void OnBar()
{
try
{
BoxHours boxHours = this.getBoxHours(Bars.OpenTimes.LastValue);
if (this.status != Status.IDLE && Bars.OpenTimes.LastValue.Hour == boxHours.startHour && Bars.OpenTimes.LastValue.Minute == this.ParamStartMinute)
{
this.status = Status.IDLE;
}
if (Bars.OpenTimes.LastValue.Hour == boxHours.endHour && Bars.OpenTimes.LastValue.Minute == this.ParamEndMinute)
{
int lastIndex = Bars.OpenTimes.GetIndexByTime(Bars.OpenTimes.Last(1));
int firstIndex = 0;
for (int j = lastIndex - 1; j > 0; j--)
{
if (Bars.OpenTimes[j].Hour == boxHours.startHour && Bars.OpenTimes[j].Minute == this.ParamStartMinute)
{
firstIndex = j;
break;
}
}
double high = Bars.HighPrices[firstIndex];
double low = Bars.LowPrices[firstIndex];
for (int k = firstIndex; k <= lastIndex; k++)
{
high = Math.Max(high, Bars.HighPrices[k]);
low = Math.Min(low, Bars.LowPrices[k]);
}
double delta = high - low;
this.hightakeProfitPrice = high + delta;
this.highStopLossPrice = high - delta;
this.highEntryPrice = high;
this.lowtakeProfitPrice = low - delta;
this.lowStopLossPrice = low + delta;
this.lowEntryPrice = low;
this.status = Status.WAITING;
Color color = Color.Lime;
if (delta < this.ParamMinBoxHeight * Symbol.PipSize || delta > this.ParamMaxBoxHeight * Symbol.PipSize)
{
color = Color.Red;
this.status = Status.IDLE;
}
if (this.ParamDrawBoxes && (this.RunningMode == RunningMode.RealTime || this.RunningMode == RunningMode.VisualBacktesting))
{
Chart.DrawRectangle(Guid.NewGuid().ToString(), firstIndex, high, lastIndex, low, color, 2);
Chart.DrawTrendLine(Guid.NewGuid().ToString(), lastIndex, high + delta, lastIndex + 20, high + delta, color);
Chart.DrawTrendLine(Guid.NewGuid().ToString(), lastIndex, low - delta, lastIndex + 20, low - delta, color);
}
}
if (this.status == Status.WAITING)
{
if (Bars.ClosePrices.LastValue > this.highEntryPrice && Bars.ClosePrices.Last(1) > this.highEntryPrice)
{
double deltaPips = (this.highEntryPrice - this.lowEntryPrice) / Symbol.PipSize;
TradeResult result = ExecuteMarketOrder(TradeType.Buy, Symbol.Name, this.calculateVolume(deltaPips), this.label, deltaPips, deltaPips);
if (result.IsSuccessful)
{
this.status = Status.TRADING;
}
}
if (Bars.ClosePrices.LastValue < this.lowEntryPrice && Bars.ClosePrices.Last(1) < this.lowEntryPrice)
{
double deltaPips = (this.highEntryPrice - this.lowEntryPrice) / Symbol.PipSize;
TradeResult result = ExecuteMarketOrder(TradeType.Sell, Symbol.Name, this.calculateVolume(deltaPips), this.label, deltaPips, deltaPips);
if (result.IsSuccessful)
{
this.status = Status.TRADING;
}
}
}
} catch (Exception exc)
{
Print(exc.Message + " " + exc.StackTrace);
throw exc;
}
}
private void onPositionClosed(PositionClosedEventArgs args)
{
if (args.Position.SymbolName.Equals(Symbol.Name) && this.label.Equals(args.Position.Label))
{
this.status = Status.IDLE;
}
}
private BoxHours getBoxHours(DateTime dt)
{
BoxHours bh = new BoxHours();
if (this.ParamAdjustSummerTime)
{
if (this.isSummer(dt))
{
bh.startHour = this.ParamStartHour - 1;
if (bh.startHour < 0)
{
bh.startHour += 24;
}
bh.endHour = this.ParamEndHour - 1;
if (bh.endHour < 0)
{
bh.endHour += 24;
}
}
else
{
bh.startHour = this.ParamStartHour;
bh.endHour = this.ParamEndHour;
}
}
else
{
bh.startHour = this.ParamStartHour;
bh.endHour = this.ParamEndHour;
}
return bh;
}
private bool isSummer(DateTime dt)
{
// Winter: November to March
// Summer: April to October
return dt.Month >= 4 && dt.Month <= 10;
}
private double calculateVolume(double stopLossPips)
{
double vol = this.volume;
switch (this.ParamMoneyMgmntType)
{
case MMType.FIXED_LOT:
vol = this.volume;
break;
case MMType.RISK:
double conversionRate = 1.0;
if (Account.Currency.Equals("EUR"))
{
Symbol symbolEURYYY = Symbols.GetSymbol("EUR" + Symbol.Name.Substring(3, 3));
conversionRate = symbolEURYYY.Bid;
}
vol = this.normalizeVolume(Account.Equity * this.ParamRisk * conversionRate / (100.0 * stopLossPips * Symbol.PipSize));
break;
}
return vol;
}
private double normalizeVolume(double vol)
{
double result = 1000;
while (result + 1000 < vol)
{
result += 1000;
}
return result;
}
}
public class BoxHours
{
public int startHour { get; set; }
public int endHour { get; set; }
}
public enum Status
{
IDLE,
WAITING,
TRADING
}
public enum MMType
{
FIXED_LOT,
RISK
}
}
Replies
cchee0324
06 Aug 2024, 14:27
( Updated at: 07 Aug 2024, 05:28 )
hi, i also facing the same problem, can i know how you solve it?
@cchee0324
firemyst
22 May 2021, 10:19
For starters it would help to know what parameter values you're using as they make a big difference.
@firemyst