Topics
10 May 2019, 10:03
 2745
 11
27 Nov 2018, 07:18
 3277
 6
Replies

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

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

screenshot

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
18 Feb 2019, 12:13

Thanks, Panagiotis

Regards, Alexader


@alexander.n.fedorov

alexander.n.fedorov
15 Feb 2019, 14:59

Thank you , Panagiotis


@alexander.n.fedorov