Topics
Replies
alexander.n.fedorov
31 Mar 2019, 11:39
( Updated at: 21 Dec 2023, 09:21 )
Sorry , the second one was wrong
the correct one is this:
@alexander.n.fedorov
alexander.n.fedorov
31 Mar 2019, 11:37
( Updated at: 21 Dec 2023, 09:21 )
I put two charts. Both have the same parameters, both OnTick , same period
first, optimization
Second - Backtesting
As you can see, they are quite different
????
@alexander.n.fedorov
alexander.n.fedorov
31 Mar 2019, 10:43
( Updated at: 21 Dec 2023, 09:21 )
I tryied, I changed to "0"
the results
using System; using System.Linq; using cAlgo.API; using cAlgo.API.Indicators; using cAlgo.API.Internals; using cAlgo.Indicators; namespace cAlgo.Robots { [Robot(TimeZone = TimeZones.RussianStandardTime, AccessRights = AccessRights.FullAccess)] public class VolatilityBreakout4 : Robot { [Parameter("Source")] public DataSeries Source { get; set; } [Parameter("Risk", MaxValue = 10, MinValue = 0.5, DefaultValue = 1)] public double Risk { get; set; } [Parameter("Squeeze bars number", MaxValue = 180, MinValue = 5, Step = 1, DefaultValue = 20)] public int SqueezeBarsNumber { get; set; } [Parameter("Squeeze in pips", MaxValue = 300, MinValue = 1, Step = 0.1, DefaultValue = 20)] public double Squeeze { get; set; } [Parameter("TP multiple", MaxValue = 8, MinValue = 1, Step = 0.1, DefaultValue = 2)] public double TpMultiple { get; set; } [Parameter("Close on Profit %", Step = 0.1, DefaultValue = 4.0)] public double CloseOnProfit { get; set; } [Parameter("Close Trade Hour", DefaultValue = 23)] public int CloseTradesHour { get; set; } [Parameter("Close Trade Minute", DefaultValue = 30)] public int CloseTradesMinute { get; set; } [Parameter("Open Trade Hour", DefaultValue = 2)] public int OpenTradesHour { get; set; } private string instance; private MarketSeries ms; private double range, high, low, volume, barsRange, SL, TP, minVolume, risk, longPrice; private double shortPrice, closeOnProfit; private int pipDigits, n; private DateTime squeezeFirstBarTime, squeezeLastBarTime; protected override void OnStart() { instance = ToString() + ", " + Symbol.Code + ", " + TimeFrame + ", " + Account.BrokerName + ", " + Account.Number; range = Squeeze * Symbol.PipSize; ms = MarketData.GetSeries(TimeFrame); minVolume = Symbol.VolumeInUnitsMin; risk = Risk * 0.01; closeOnProfit = CloseOnProfit * 0.01; pipDigits = Symbol.Digits - (int)Math.Log10(1 / Symbol.PipSize); Positions.Opened += Positions_Opened; Positions.Closed += PositionsOnClosed; squeezeFirstBarTime = CandleOpenTime(2 + SqueezeBarsNumber); squeezeLastBarTime = CandleOpenTime(2); } protected override void OnBar() { var position = Positions.Find(instance); var spread = Symbol.Spread / Symbol.PipSize; if (position == null) { if (spread > 2) { return; } if ((CandleOpenTime(0).Hour >= CloseTradesHour && CandleOpenTime(0).Minute >= CloseTradesMinute) || CandleOpenTime(0).Hour < OpenTradesHour) { return; } squeezeFirstBarTime = CandleOpenTime(1 + SqueezeBarsNumber); squeezeLastBarTime = CandleOpenTime(1); high = CandleHigh(1); low = CandleLow(1); barsRange = CandleClose(1) > (1) ? MarketSeries.Close.Last(1) - MarketSeries.Open.Last(1) : MarketSeries.Open.Last(1) - MarketSeries.Close.Last(1); for (int i = 0; i < SqueezeBarsNumber; i++) { high = CandleHigh(i + 1) > high ? CandleHigh(i + 1) : high; low = CandleLow(i + 1) < low ? CandleLow(i + 1) : low; barsRange = high - low; } //Chart.RemoveAllObjects(); //Chart.DrawTrendLine("sHigh", squeezeFirstBarTime, high, squeezeLastBarTime, high, Color.Aqua, 1, LineStyle.Solid); //Chart.DrawTrendLine("sLow", squeezeFirstBarTime, low, squeezeLastBarTime, low, Color.Red, 1, LineStyle.Solid); //double barRangePips = Math.Round(barsRange / Symbol.PipSize, 1); //string text = "Squeeze = " + Squeeze + " , barRange = " + barRangePips; //Chart.DrawStaticText("Current range", text, VerticalAlignment.Bottom, HorizontalAlignment.Right, Color.Aquamarine); n = 0; foreach (var order in PendingOrders) { if (order.Label == instance) { n = n + 1; } } if (n == 0) { if (high - low < range) { { longPrice = high; shortPrice = low; SL = (high - low) / Symbol.PipSize + 1; volume = Math.Floor(((Account.Equity * risk) / SL) / Symbol.PipValue / minVolume) * minVolume; SL = Math.Round(SL, pipDigits, 0); TP = Math.Round(SL * TpMultiple, pipDigits, 0); PlaceStopOrder(TradeType.Buy, Symbol, volume, longPrice, instance, null, TP); PlaceStopOrder(TradeType.Sell, Symbol, volume, shortPrice, instance, null, TP); //Chart.DrawHorizontalLine(longPrice.ToString(), longPrice - SL * Symbol.PipSize, Color.Crimson, 1, LineStyle.DotsRare); //Chart.DrawHorizontalLine(shortPrice.ToString(), shortPrice + SL * Symbol.PipSize, Color.Crimson, 1, LineStyle.DotsRare); } } } } if (position != null) { if (spread > 2) { return; } if (position.TradeType == TradeType.Buy) { if (CandleClose(1) < position.EntryPrice - SL * Symbol.PipSize) { ClosePosition(position); //Chart.RemoveAllObjects(); } } if (position.TradeType == TradeType.Sell) { if (CandleClose(1) > position.EntryPrice + SL * Symbol.PipSize) { ClosePosition(position); //Chart.RemoveAllObjects(); } } } } protected override void OnTick() { if (Account.UnrealizedNetProfit > Account.Balance * closeOnProfit) foreach (var position in Positions) { ClosePositionAsync(position); } } private void Positions_Opened(PositionOpenedEventArgs args) { var position = args.Position; if (position.Label == instance) { foreach (var order in PendingOrders) { if (order.Label == instance) CancelPendingOrder(order); } if (position.TradeType == TradeType.Buy) { //Chart.RemoveObject(shortPrice.ToString()); } if (position.TradeType == TradeType.Sell) { //Chart.RemoveObject(longPrice.ToString()); } } } private void PositionsOnClosed(PositionClosedEventArgs args) { var position = args.Position; if (args.Reason == PositionCloseReason.TakeProfit) { // } } #region Candles Processing #region Candle Type private bool CandleTypeBullish(int k) { if (ms.Open.Last(k) > ms.Close.Last(k)) { return false; } return true; } #endregion #region Candle Range(int k) private double CandleRange(int k) { return ms.High.Last(k) - ms.Low.Last(k); } #endregion #region Candle body bottom private double CandleBodyBottom(int k) { return (ms.Open.Last(k) < ms.Close.Last(k)) ? ms.Open.Last(k) : ms.Close.Last(k); } #endregion #region Candle body Top private double CandleBodyTop(int k) { return (ms.Open.Last(k) > ms.Close.Last(k)) ? ms.Open.Last(k) : ms.Close.Last(k); } #endregion #region Candle high private double CandleHigh(int k) { return ms.High.Last(k); } #endregion #region Candle low private double CandleLow(int k) { return ms.Low.Last(k); } #endregion #region Candle body private double CandleBody(int k) { return Math.Abs((ms.Open.Last(k) - ms.Close.Last(k))); } #endregion #region Candle Close private double CandleClose(int k) { if (CandleTypeBullish(k)) { return CandleBodyTop(k); } return CandleBodyBottom(k); } #endregion #region Candle Open private double CandleOpen(int k) { if (CandleTypeBullish(k)) { return CandleBodyBottom(k); } return CandleBodyTop(k); } #endregion #region Candle Sinus private double CandleSinus(int k) { return Math.Abs((ms.Open.Last(k) - ms.Close.Last(k))) / CandleRange(k) * (ms.Close.Last(k) > ms.Open.Last(k) ? 1 : -1); } #endregion #region Trend Angle private double TrendAngle(int CandlesInTrend) { double absBody = 0; double bodiesRange = 0; for (int i = 0; i <= CandlesInTrend; i++) { if (CandleTypeBullish(i)) { bodiesRange = bodiesRange + CandleBody(i); } if (!CandleTypeBullish(i)) { bodiesRange = bodiesRange - CandleBody(i); } absBody = absBody + CandleBody(i); } var trendSinus = bodiesRange / absBody; return Math.Asin(trendSinus) * 180 / Math.PI; } #endregion #region Candle OpenTime private DateTime CandleOpenTime(int k) { return ms.OpenTime.Last(k); } #endregion #region No k Candles on the left High private bool NoLeftCandlesHigh(int k) { for (int i = 1; i < k; i++) { if (CandleHigh(1) > CandleLow(1 + i) && CandleHigh(1) < CandleHigh(1 + i)) { return false; } if (CandleHigh(1) < CandleLow(1 + i) || CandleHigh(1) > CandleHigh(1 + i)) { continue; } } return true; } #endregion #region No k Candles on the left Low private bool NoLeftCandlesLow(int k) { for (int i = 1; i < k; i++) { if (CandleLow(1) < CandleHigh(1 + i) && CandleLow(1) > CandleLow(1 + i)) { return false; } if (CandleLow(1) < CandleHigh(1 + i) || CandleLow(1) > CandleLow(1 + i)) { continue; } } return true; } #endregion #endregion } }
I commented the charts. Charts do not work on optimization.
I also introduced the OnTick logic, as it may improve the working with portfolio
But the poin is that about a month ago everthing was working perfectly
Now - not
during this time there were some updates on the software. Could that be the reason?
Regards,
Alexander
@alexander.n.fedorov
alexander.n.fedorov
31 Mar 2019, 10:30
RE:
tradermatrix said:
Hi
I think the problem is here;
SL = Math.Round(SL, pipDigits, MidpointRounding.AwayFromZero);
I just replaced ("MidpointRounding.AwayFromZero") with 0 and it works
SL = Math.Round(SL, pipDigits, 0);
TP = SL * TpMultiple;
PlaceStopOrder(TradeType.Buy, Symbol, volume, longPrice, instance, SL, TP);
PlaceStopOrder(TradeType.Sell, Symbol, volume, shortPrice, instance, SL, TP);cordially
Thank you. Let me try
Also before I tryied I wannted to say it is not working on tick either
@alexander.n.fedorov
alexander.n.fedorov
30 Mar 2019, 11:18
I just tryied to do optimization on tick data. Result is the same. Optimization and the backtest - absolutely different results
@alexander.n.fedorov
alexander.n.fedorov
30 Mar 2019, 11:15
( Updated at: 21 Dec 2023, 09:21 )
RE:
lukas.ourada said:
Hi, i have problem with run optimization for my cBot. Backtesting works good, but if i run optimization not have any result, not position open and is end while 3sec.
what is wrong? Its bug?
I try change parameters, unchecked it and try my two other cBot and same result...
Please help
Try to read what log says, just make sure it shows all the information ("All events")
@alexander.n.fedorov
alexander.n.fedorov
30 Mar 2019, 10:57
( Updated at: 21 Dec 2023, 09:21 )
RE: RE: RE:
alexander.n.fedorov said:
alexander.n.fedorov said:
alexander.n.fedorov said:
Dear Panagiotis!
There must be sum bug in optimizations.
I will put three charts here and a zip of the bot
Optimization and backtesting show complitely different results, even thou all the condititons according to "apply
"
in both cases parameteres are the same, 1 minuter data,dates are the same, only one timeframe
What is interesting, sometimes it repeats perfectly
Sometimes - nothing in common.
using System; using System.Linq; using cAlgo.API; using cAlgo.API.Indicators; using cAlgo.API.Internals; using cAlgo.Indicators; namespace cAlgo.Robots { [Robot(TimeZone = TimeZones.RussianStandardTime, AccessRights = AccessRights.None)] public class VolatilityBreakout4 : Robot { [Parameter("Source")] public DataSeries Source { get; set; } [Parameter("Risk", MaxValue = 10, MinValue = 0.5, DefaultValue = 1)] public double Risk { get; set; } [Parameter("Squeeze bars number", MaxValue = 180, MinValue = 5, Step = 1, DefaultValue = 20)] public int SqueezeBarsNumber { get; set; } [Parameter("Squeeze in pips", MaxValue = 300, MinValue = 1, Step = 0.1, DefaultValue = 20)] public double Squeeze { get; set; } [Parameter("TP multiple", MaxValue = 8, MinValue = 1, Step = 0.1, DefaultValue = 2)] public double TpMultiple { get; set; } [Parameter("Close Trade Hour", DefaultValue = 23)] public int CloseTradesHour { get; set; } [Parameter("Close Trade Minute", DefaultValue = 30)] public int CloseTradesMinute { get; set; } [Parameter("Open Trade Hour", DefaultValue = 2)] public int OpenTradesHour { get; set; } private string instance; private MarketSeries ms; private double range, high, low, volume, barsRange, SL, TP, minVolume, risk; private int pipDigits, n; private DateTime squeezeFirstBarTime, squeezeLastBarTime; private TimeSpan ts; protected override void OnStart() { instance = ToString() + ", " + Symbol.Code + ", " + TimeFrame + ", " + Account.BrokerName + ", " + Account.Number; range = Squeeze * Symbol.PipSize; ms = MarketData.GetSeries(TimeFrame); minVolume = Symbol.VolumeInUnitsMin; ts = CandleOpenTime(0) - CandleOpenTime(2); risk = Risk * 0.01; pipDigits = Symbol.Digits - (int)Math.Log10(1 / Symbol.PipSize); Positions.Opened += Positions_Opened; Positions.Closed += PositionsOnClosed; squeezeFirstBarTime = CandleOpenTime(2 + SqueezeBarsNumber); squeezeLastBarTime = CandleOpenTime(2); } protected override void OnBar() { if ((CandleOpenTime(0).Hour >= CloseTradesHour && CandleOpenTime(0).Minute >= CloseTradesMinute) || CandleOpenTime(0).Hour < OpenTradesHour) { return; } squeezeFirstBarTime = CandleOpenTime(1 + SqueezeBarsNumber); squeezeLastBarTime = CandleOpenTime(1); high = CandleHigh(1); low = CandleLow(1); barsRange = CandleClose(1) > (1) ? MarketSeries.Close.Last(1) - MarketSeries.Open.Last(1) : MarketSeries.Open.Last(1) - MarketSeries.Close.Last(1); for (int i = 0; i < SqueezeBarsNumber; i++) { high = CandleHigh(i + 1) > high ? CandleHigh(i + 1) : high; low = CandleLow(i + 1) < low ? CandleLow(i + 1) : low; barsRange = high - low; } //Chart.RemoveAllObjects(); //Chart.DrawTrendLine("sHigh", squeezeFirstBarTime, high, squeezeLastBarTime, high, Color.Aqua, 1, LineStyle.Solid); //Chart.DrawTrendLine("sLow", squeezeFirstBarTime, low, squeezeLastBarTime, low, Color.Red, 1, LineStyle.Solid); //double barRangePips = Math.Round(barsRange / Symbol.PipSize, 1); //string text = "Squeeze = " + Squeeze + " , barRange = " + barRangePips; //Chart.DrawStaticText("Current range", text, VerticalAlignment.Bottom, HorizontalAlignment.Right, Color.Aquamarine); var position = Positions.Find(instance); if (position != null) { return; } n = 0; foreach (var order in PendingOrders) { if (order.Label == instance) { n = n + 1; } } if (position == null) { if (n == 0) { if (high - low < range) { double longPrice = high; double shortPrice = low; SL = (high - low) / Symbol.PipSize; volume = Math.Floor(((Account.Equity * risk) / SL) / Symbol.PipValue / minVolume) * minVolume; SL = Math.Round(SL, pipDigits, MidpointRounding.AwayFromZero); TP = SL * TpMultiple; PlaceStopOrder(TradeType.Buy, Symbol, volume, longPrice, instance, SL, TP); PlaceStopOrder(TradeType.Sell, Symbol, volume, shortPrice, instance, SL, TP); } } } } private void Positions_Opened(PositionOpenedEventArgs args) { var position = args.Position; if (position.Label == instance) { foreach (var order in PendingOrders) { if (order.Label == instance) CancelPendingOrder(order); } } } private void PositionsOnClosed(PositionClosedEventArgs args) { var position = args.Position; if (args.Reason == PositionCloseReason.TakeProfit) { //if (Server.Time - position.EntryTime < ts) //{ // ExecuteMarketOrder(position.TradeType, Symbol, volume, instance, SL, SL); //} //// foreach (var order in PendingOrders) // { // if (order.Label == instance) // CancelPendingOrder(order); // } //} } } #region Candles Processing #region Candle Type private bool CandleTypeBullish(int k) { if (ms.Open.Last(k) > ms.Close.Last(k)) { return false; } return true; } #endregion #region Candle Range(int k) private double CandleRange(int k) { return ms.High.Last(k) - ms.Low.Last(k); } #endregion #region Candle body bottom private double CandleBodyBottom(int k) { return (ms.Open.Last(k) < ms.Close.Last(k)) ? ms.Open.Last(k) : ms.Close.Last(k); } #endregion #region Candle body Top private double CandleBodyTop(int k) { return (ms.Open.Last(k) > ms.Close.Last(k)) ? ms.Open.Last(k) : ms.Close.Last(k); } #endregion #region Candle high private double CandleHigh(int k) { return ms.High.Last(k); } #endregion #region Candle low private double CandleLow(int k) { return ms.Low.Last(k); } #endregion #region Candle body private double CandleBody(int k) { return Math.Abs((ms.Open.Last(k) - ms.Close.Last(k))); } #endregion #region Candle Close private double CandleClose(int k) { if (CandleTypeBullish(k)) { return CandleBodyTop(k); } return CandleBodyBottom(k); } #endregion #region Candle Open private double CandleOpen(int k) { if (CandleTypeBullish(k)) { return CandleBodyBottom(k); } return CandleBodyTop(k); } #endregion #region Candle Sinus private double CandleSinus(int k) { return Math.Abs((ms.Open.Last(k) - ms.Close.Last(k))) / CandleRange(k) * (ms.Close.Last(k) > ms.Open.Last(k) ? 1 : -1); } #endregion #region Trend Angle private double TrendAngle(int CandlesInTrend) { double absBody = 0; double bodiesRange = 0; for (int i = 0; i <= CandlesInTrend; i++) { if (CandleTypeBullish(i)) { bodiesRange = bodiesRange + CandleBody(i); } if (!CandleTypeBullish(i)) { bodiesRange = bodiesRange - CandleBody(i); } absBody = absBody + CandleBody(i); } var trendSinus = bodiesRange / absBody; return Math.Asin(trendSinus) * 180 / Math.PI; } #endregion #region Candle OpenTime private DateTime CandleOpenTime(int k) { return ms.OpenTime.Last(k); } #endregion #region No k Candles on the left High private bool NoLeftCandlesHigh(int k) { for (int i = 1; i < k; i++) { if (CandleHigh(1) > CandleLow(1 + i) && CandleHigh(1) < CandleHigh(1 + i)) { return false; } if (CandleHigh(1) < CandleLow(1 + i) || CandleHigh(1) > CandleHigh(1 + i)) { continue; } } return true; } #endregion #region No k Candles on the left Low private bool NoLeftCandlesLow(int k) { for (int i = 1; i < k; i++) { if (CandleLow(1) < CandleHigh(1 + i) && CandleLow(1) > CandleLow(1 + i)) { return false; } if (CandleLow(1) < CandleHigh(1 + i) || CandleLow(1) > CandleLow(1 + i)) { continue; } } return true; } #endregion #endregion } }
I think Spotware have to do smth about it, otherwise the whole idea of cTrader Algos is becoming useless
Regadrs
Alexander
P.S. What is interesting, this effect appeared just recently. Before my previous mail everything worked allright. May it is one of the constant upgrades?
@alexander.n.fedorov
alexander.n.fedorov
30 Mar 2019, 10:50
( Updated at: 21 Dec 2023, 09:21 )
RE: RE:
alexander.n.fedorov said:
alexander.n.fedorov said:
Dear Panagiotis!
There must be sum bug in optimizations.
I will put three charts here and a zip of the bot
Optimization and backtesting show complitely different results, even thou all the condititons according to "apply
"
in both cases parameteres are the same, 1 minuter data,dates are the same, only one timeframe
What is interesting, sometimes it repeats perfectly
Sometimes - nothing in common.
using System; using System.Linq; using cAlgo.API; using cAlgo.API.Indicators; using cAlgo.API.Internals; using cAlgo.Indicators; namespace cAlgo.Robots { [Robot(TimeZone = TimeZones.RussianStandardTime, AccessRights = AccessRights.None)] public class VolatilityBreakout4 : Robot { [Parameter("Source")] public DataSeries Source { get; set; } [Parameter("Risk", MaxValue = 10, MinValue = 0.5, DefaultValue = 1)] public double Risk { get; set; } [Parameter("Squeeze bars number", MaxValue = 180, MinValue = 5, Step = 1, DefaultValue = 20)] public int SqueezeBarsNumber { get; set; } [Parameter("Squeeze in pips", MaxValue = 300, MinValue = 1, Step = 0.1, DefaultValue = 20)] public double Squeeze { get; set; } [Parameter("TP multiple", MaxValue = 8, MinValue = 1, Step = 0.1, DefaultValue = 2)] public double TpMultiple { get; set; } [Parameter("Close Trade Hour", DefaultValue = 23)] public int CloseTradesHour { get; set; } [Parameter("Close Trade Minute", DefaultValue = 30)] public int CloseTradesMinute { get; set; } [Parameter("Open Trade Hour", DefaultValue = 2)] public int OpenTradesHour { get; set; } private string instance; private MarketSeries ms; private double range, high, low, volume, barsRange, SL, TP, minVolume, risk; private int pipDigits, n; private DateTime squeezeFirstBarTime, squeezeLastBarTime; private TimeSpan ts; protected override void OnStart() { instance = ToString() + ", " + Symbol.Code + ", " + TimeFrame + ", " + Account.BrokerName + ", " + Account.Number; range = Squeeze * Symbol.PipSize; ms = MarketData.GetSeries(TimeFrame); minVolume = Symbol.VolumeInUnitsMin; ts = CandleOpenTime(0) - CandleOpenTime(2); risk = Risk * 0.01; pipDigits = Symbol.Digits - (int)Math.Log10(1 / Symbol.PipSize); Positions.Opened += Positions_Opened; Positions.Closed += PositionsOnClosed; squeezeFirstBarTime = CandleOpenTime(2 + SqueezeBarsNumber); squeezeLastBarTime = CandleOpenTime(2); } protected override void OnBar() { if ((CandleOpenTime(0).Hour >= CloseTradesHour && CandleOpenTime(0).Minute >= CloseTradesMinute) || CandleOpenTime(0).Hour < OpenTradesHour) { return; } squeezeFirstBarTime = CandleOpenTime(1 + SqueezeBarsNumber); squeezeLastBarTime = CandleOpenTime(1); high = CandleHigh(1); low = CandleLow(1); barsRange = CandleClose(1) > (1) ? MarketSeries.Close.Last(1) - MarketSeries.Open.Last(1) : MarketSeries.Open.Last(1) - MarketSeries.Close.Last(1); for (int i = 0; i < SqueezeBarsNumber; i++) { high = CandleHigh(i + 1) > high ? CandleHigh(i + 1) : high; low = CandleLow(i + 1) < low ? CandleLow(i + 1) : low; barsRange = high - low; } //Chart.RemoveAllObjects(); //Chart.DrawTrendLine("sHigh", squeezeFirstBarTime, high, squeezeLastBarTime, high, Color.Aqua, 1, LineStyle.Solid); //Chart.DrawTrendLine("sLow", squeezeFirstBarTime, low, squeezeLastBarTime, low, Color.Red, 1, LineStyle.Solid); //double barRangePips = Math.Round(barsRange / Symbol.PipSize, 1); //string text = "Squeeze = " + Squeeze + " , barRange = " + barRangePips; //Chart.DrawStaticText("Current range", text, VerticalAlignment.Bottom, HorizontalAlignment.Right, Color.Aquamarine); var position = Positions.Find(instance); if (position != null) { return; } n = 0; foreach (var order in PendingOrders) { if (order.Label == instance) { n = n + 1; } } if (position == null) { if (n == 0) { if (high - low < range) { double longPrice = high; double shortPrice = low; SL = (high - low) / Symbol.PipSize; volume = Math.Floor(((Account.Equity * risk) / SL) / Symbol.PipValue / minVolume) * minVolume; SL = Math.Round(SL, pipDigits, MidpointRounding.AwayFromZero); TP = SL * TpMultiple; PlaceStopOrder(TradeType.Buy, Symbol, volume, longPrice, instance, SL, TP); PlaceStopOrder(TradeType.Sell, Symbol, volume, shortPrice, instance, SL, TP); } } } } private void Positions_Opened(PositionOpenedEventArgs args) { var position = args.Position; if (position.Label == instance) { foreach (var order in PendingOrders) { if (order.Label == instance) CancelPendingOrder(order); } } } private void PositionsOnClosed(PositionClosedEventArgs args) { var position = args.Position; if (args.Reason == PositionCloseReason.TakeProfit) { //if (Server.Time - position.EntryTime < ts) //{ // ExecuteMarketOrder(position.TradeType, Symbol, volume, instance, SL, SL); //} //// foreach (var order in PendingOrders) // { // if (order.Label == instance) // CancelPendingOrder(order); // } //} } } #region Candles Processing #region Candle Type private bool CandleTypeBullish(int k) { if (ms.Open.Last(k) > ms.Close.Last(k)) { return false; } return true; } #endregion #region Candle Range(int k) private double CandleRange(int k) { return ms.High.Last(k) - ms.Low.Last(k); } #endregion #region Candle body bottom private double CandleBodyBottom(int k) { return (ms.Open.Last(k) < ms.Close.Last(k)) ? ms.Open.Last(k) : ms.Close.Last(k); } #endregion #region Candle body Top private double CandleBodyTop(int k) { return (ms.Open.Last(k) > ms.Close.Last(k)) ? ms.Open.Last(k) : ms.Close.Last(k); } #endregion #region Candle high private double CandleHigh(int k) { return ms.High.Last(k); } #endregion #region Candle low private double CandleLow(int k) { return ms.Low.Last(k); } #endregion #region Candle body private double CandleBody(int k) { return Math.Abs((ms.Open.Last(k) - ms.Close.Last(k))); } #endregion #region Candle Close private double CandleClose(int k) { if (CandleTypeBullish(k)) { return CandleBodyTop(k); } return CandleBodyBottom(k); } #endregion #region Candle Open private double CandleOpen(int k) { if (CandleTypeBullish(k)) { return CandleBodyBottom(k); } return CandleBodyTop(k); } #endregion #region Candle Sinus private double CandleSinus(int k) { return Math.Abs((ms.Open.Last(k) - ms.Close.Last(k))) / CandleRange(k) * (ms.Close.Last(k) > ms.Open.Last(k) ? 1 : -1); } #endregion #region Trend Angle private double TrendAngle(int CandlesInTrend) { double absBody = 0; double bodiesRange = 0; for (int i = 0; i <= CandlesInTrend; i++) { if (CandleTypeBullish(i)) { bodiesRange = bodiesRange + CandleBody(i); } if (!CandleTypeBullish(i)) { bodiesRange = bodiesRange - CandleBody(i); } absBody = absBody + CandleBody(i); } var trendSinus = bodiesRange / absBody; return Math.Asin(trendSinus) * 180 / Math.PI; } #endregion #region Candle OpenTime private DateTime CandleOpenTime(int k) { return ms.OpenTime.Last(k); } #endregion #region No k Candles on the left High private bool NoLeftCandlesHigh(int k) { for (int i = 1; i < k; i++) { if (CandleHigh(1) > CandleLow(1 + i) && CandleHigh(1) < CandleHigh(1 + i)) { return false; } if (CandleHigh(1) < CandleLow(1 + i) || CandleHigh(1) > CandleHigh(1 + i)) { continue; } } return true; } #endregion #region No k Candles on the left Low private bool NoLeftCandlesLow(int k) { for (int i = 1; i < k; i++) { if (CandleLow(1) < CandleHigh(1 + i) && CandleLow(1) > CandleLow(1 + i)) { return false; } if (CandleLow(1) < CandleHigh(1 + i) || CandleLow(1) > CandleLow(1 + i)) { continue; } } return true; } #endregion #endregion } }
I think Spotware have to do smth about it, otherwise the whole idea of cTrader Algos is becoming useless
Regadrs
Alexander
@alexander.n.fedorov
alexander.n.fedorov
30 Mar 2019, 10:44
( Updated at: 21 Dec 2023, 09:21 )
RE:
alexander.n.fedorov said:
Dear Panagiotis!
There must be sum bug in optimizations.
I will put three charts here and a zip of the bot
Optimization and backtesting show complitely different results, even thou all the condititons according to "apply
"
in both cases parameteres are the same, 1 minuter data,dates are the same, only one timeframe
What is interesting, sometimes it repeats perfectly
Sometimes - nothing in common.
using System; using System.Linq; using cAlgo.API; using cAlgo.API.Indicators; using cAlgo.API.Internals; using cAlgo.Indicators; namespace cAlgo.Robots { [Robot(TimeZone = TimeZones.RussianStandardTime, AccessRights = AccessRights.None)] public class VolatilityBreakout4 : Robot { [Parameter("Source")] public DataSeries Source { get; set; } [Parameter("Risk", MaxValue = 10, MinValue = 0.5, DefaultValue = 1)] public double Risk { get; set; } [Parameter("Squeeze bars number", MaxValue = 180, MinValue = 5, Step = 1, DefaultValue = 20)] public int SqueezeBarsNumber { get; set; } [Parameter("Squeeze in pips", MaxValue = 300, MinValue = 1, Step = 0.1, DefaultValue = 20)] public double Squeeze { get; set; } [Parameter("TP multiple", MaxValue = 8, MinValue = 1, Step = 0.1, DefaultValue = 2)] public double TpMultiple { get; set; } [Parameter("Close Trade Hour", DefaultValue = 23)] public int CloseTradesHour { get; set; } [Parameter("Close Trade Minute", DefaultValue = 30)] public int CloseTradesMinute { get; set; } [Parameter("Open Trade Hour", DefaultValue = 2)] public int OpenTradesHour { get; set; } private string instance; private MarketSeries ms; private double range, high, low, volume, barsRange, SL, TP, minVolume, risk; private int pipDigits, n; private DateTime squeezeFirstBarTime, squeezeLastBarTime; private TimeSpan ts; protected override void OnStart() { instance = ToString() + ", " + Symbol.Code + ", " + TimeFrame + ", " + Account.BrokerName + ", " + Account.Number; range = Squeeze * Symbol.PipSize; ms = MarketData.GetSeries(TimeFrame); minVolume = Symbol.VolumeInUnitsMin; ts = CandleOpenTime(0) - CandleOpenTime(2); risk = Risk * 0.01; pipDigits = Symbol.Digits - (int)Math.Log10(1 / Symbol.PipSize); Positions.Opened += Positions_Opened; Positions.Closed += PositionsOnClosed; squeezeFirstBarTime = CandleOpenTime(2 + SqueezeBarsNumber); squeezeLastBarTime = CandleOpenTime(2); } protected override void OnBar() { if ((CandleOpenTime(0).Hour >= CloseTradesHour && CandleOpenTime(0).Minute >= CloseTradesMinute) || CandleOpenTime(0).Hour < OpenTradesHour) { return; } squeezeFirstBarTime = CandleOpenTime(1 + SqueezeBarsNumber); squeezeLastBarTime = CandleOpenTime(1); high = CandleHigh(1); low = CandleLow(1); barsRange = CandleClose(1) > (1) ? MarketSeries.Close.Last(1) - MarketSeries.Open.Last(1) : MarketSeries.Open.Last(1) - MarketSeries.Close.Last(1); for (int i = 0; i < SqueezeBarsNumber; i++) { high = CandleHigh(i + 1) > high ? CandleHigh(i + 1) : high; low = CandleLow(i + 1) < low ? CandleLow(i + 1) : low; barsRange = high - low; } //Chart.RemoveAllObjects(); //Chart.DrawTrendLine("sHigh", squeezeFirstBarTime, high, squeezeLastBarTime, high, Color.Aqua, 1, LineStyle.Solid); //Chart.DrawTrendLine("sLow", squeezeFirstBarTime, low, squeezeLastBarTime, low, Color.Red, 1, LineStyle.Solid); //double barRangePips = Math.Round(barsRange / Symbol.PipSize, 1); //string text = "Squeeze = " + Squeeze + " , barRange = " + barRangePips; //Chart.DrawStaticText("Current range", text, VerticalAlignment.Bottom, HorizontalAlignment.Right, Color.Aquamarine); var position = Positions.Find(instance); if (position != null) { return; } n = 0; foreach (var order in PendingOrders) { if (order.Label == instance) { n = n + 1; } } if (position == null) { if (n == 0) { if (high - low < range) { double longPrice = high; double shortPrice = low; SL = (high - low) / Symbol.PipSize; volume = Math.Floor(((Account.Equity * risk) / SL) / Symbol.PipValue / minVolume) * minVolume; SL = Math.Round(SL, pipDigits, MidpointRounding.AwayFromZero); TP = SL * TpMultiple; PlaceStopOrder(TradeType.Buy, Symbol, volume, longPrice, instance, SL, TP); PlaceStopOrder(TradeType.Sell, Symbol, volume, shortPrice, instance, SL, TP); } } } } private void Positions_Opened(PositionOpenedEventArgs args) { var position = args.Position; if (position.Label == instance) { foreach (var order in PendingOrders) { if (order.Label == instance) CancelPendingOrder(order); } } } private void PositionsOnClosed(PositionClosedEventArgs args) { var position = args.Position; if (args.Reason == PositionCloseReason.TakeProfit) { //if (Server.Time - position.EntryTime < ts) //{ // ExecuteMarketOrder(position.TradeType, Symbol, volume, instance, SL, SL); //} //// foreach (var order in PendingOrders) // { // if (order.Label == instance) // CancelPendingOrder(order); // } //} } } #region Candles Processing #region Candle Type private bool CandleTypeBullish(int k) { if (ms.Open.Last(k) > ms.Close.Last(k)) { return false; } return true; } #endregion #region Candle Range(int k) private double CandleRange(int k) { return ms.High.Last(k) - ms.Low.Last(k); } #endregion #region Candle body bottom private double CandleBodyBottom(int k) { return (ms.Open.Last(k) < ms.Close.Last(k)) ? ms.Open.Last(k) : ms.Close.Last(k); } #endregion #region Candle body Top private double CandleBodyTop(int k) { return (ms.Open.Last(k) > ms.Close.Last(k)) ? ms.Open.Last(k) : ms.Close.Last(k); } #endregion #region Candle high private double CandleHigh(int k) { return ms.High.Last(k); } #endregion #region Candle low private double CandleLow(int k) { return ms.Low.Last(k); } #endregion #region Candle body private double CandleBody(int k) { return Math.Abs((ms.Open.Last(k) - ms.Close.Last(k))); } #endregion #region Candle Close private double CandleClose(int k) { if (CandleTypeBullish(k)) { return CandleBodyTop(k); } return CandleBodyBottom(k); } #endregion #region Candle Open private double CandleOpen(int k) { if (CandleTypeBullish(k)) { return CandleBodyBottom(k); } return CandleBodyTop(k); } #endregion #region Candle Sinus private double CandleSinus(int k) { return Math.Abs((ms.Open.Last(k) - ms.Close.Last(k))) / CandleRange(k) * (ms.Close.Last(k) > ms.Open.Last(k) ? 1 : -1); } #endregion #region Trend Angle private double TrendAngle(int CandlesInTrend) { double absBody = 0; double bodiesRange = 0; for (int i = 0; i <= CandlesInTrend; i++) { if (CandleTypeBullish(i)) { bodiesRange = bodiesRange + CandleBody(i); } if (!CandleTypeBullish(i)) { bodiesRange = bodiesRange - CandleBody(i); } absBody = absBody + CandleBody(i); } var trendSinus = bodiesRange / absBody; return Math.Asin(trendSinus) * 180 / Math.PI; } #endregion #region Candle OpenTime private DateTime CandleOpenTime(int k) { return ms.OpenTime.Last(k); } #endregion #region No k Candles on the left High private bool NoLeftCandlesHigh(int k) { for (int i = 1; i < k; i++) { if (CandleHigh(1) > CandleLow(1 + i) && CandleHigh(1) < CandleHigh(1 + i)) { return false; } if (CandleHigh(1) < CandleLow(1 + i) || CandleHigh(1) > CandleHigh(1 + i)) { continue; } } return true; } #endregion #region No k Candles on the left Low private bool NoLeftCandlesLow(int k) { for (int i = 1; i < k; i++) { if (CandleLow(1) < CandleHigh(1 + i) && CandleLow(1) > CandleLow(1 + i)) { return false; } if (CandleLow(1) < CandleHigh(1 + i) || CandleLow(1) > CandleLow(1 + i)) { continue; } } return true; } #endregion #endregion } }
@alexander.n.fedorov
alexander.n.fedorov
21 Mar 2019, 16:54
Hi, Panagiotis.
How about if I want to go back a couple of month and see it on a 5 min chart?
Regards,
Sasha
@alexander.n.fedorov
alexander.n.fedorov
07 Mar 2019, 17:37
RE: RE:
alexander.n.fedorov said:
Panagiotis Charalampous said:
Hi Sasha,
I have checked your cBot and you are using data from another timeframe
[Parameter("S & R TimeFrame", DefaultValue = "Daily")] public TimeFrame SRTimframe { get; set; } . . . seriesSR = MarketData.GetSeries(SRTimframe); . . . .Best Regards,
Panagiotis
O , that is tru. I thought you were saying that I do backtesting on different timeframe, then optimization
But that is still a bug
Best regards,
Alexander
P. S. And thank you very much for checking
@alexander.n.fedorov
alexander.n.fedorov
07 Mar 2019, 17:36
RE:
Panagiotis Charalampous said:
Hi Sasha,
I have checked your cBot and you are using data from another timeframe
[Parameter("S & R TimeFrame", DefaultValue = "Daily")] public TimeFrame SRTimframe { get; set; } . . . seriesSR = MarketData.GetSeries(SRTimframe); . . . .Best Regards,
Panagiotis
O , that is tru. I thought you were saying that I do backtesting on different timeframe, then optimization
But that is still a bug
Best regards,
Alexander
@alexander.n.fedorov
alexander.n.fedorov
06 Mar 2019, 11:53
RE:
Panagiotis Charalampous said:
Hi Sasha,
Can you please share the code then?
Best Regards,
Panagiotis
I sent it to you
@alexander.n.fedorov
alexander.n.fedorov
05 Mar 2019, 21:26
RE:
Panagiotis Charalampous said:
Hi Sasha,
This happens only when you are using data from another timeframe. If you do so then this is the reason.
Best Regards,
Panagiotis
TimeFrame is the same
@alexander.n.fedorov
alexander.n.fedorov
05 Mar 2019, 14:24
There is no prob to give you source code. It is just a simple Big Shadow strategy
I was trying to use optimizor, cause different pairs have differen behaviour
But, if you need code, just tell me, no prob
@alexander.n.fedorov
alexander.n.fedorov
05 Mar 2019, 14:09
RE:
Panagiotis Charalampous said:
Hi Sasha,
It is probably related to this issue.
Best Regards,
Panagiotis
So, it is known bug?
@alexander.n.fedorov
alexander.n.fedorov
05 Mar 2019, 12:58
( Updated at: 21 Dec 2023, 09:21 )
RE:
alexander.n.fedorov said:
Dear Panagiotis!
It looks like there is a big bug in tester-optimizer/
The way I see the optimization is done is this
1. You do optimization with a set of parameters
2. You select certain result and push the "Apply" green button
3. when you do that all the timing, onTick, comissions and parameters are copied to backtester
4. You run backtest and , theoretically, and as it always was happening, must get the same results
in this case it did not work like that
see the images:
@alexander.n.fedorov
alexander.n.fedorov
31 Mar 2019, 13:05
Hi!
Because I am quite new to the programming in C# I do not quite understand what shall I do with the link?
Shall I just down load the runtime? I am using Visual Studio for writing a code
Regards
Alexander
@alexander.n.fedorov