Visual Mode for BackTesting

Created at 22 Mar 2018, 20:08
How’s your experience with the cTrader Platform?
Your feedback is crucial to cTrader's development. Please take a few seconds to share your opinion and help us improve your trading experience. Thanks!
YJ

yjoura

Joined 22.03.2018

Visual Mode for BackTesting
22 Mar 2018, 20:08


Hi All,
This page https://spotware.com/ctrader/trading/ctrader-automated-trading-platform
Claims that backtesting visual mode is there. But its actually not in the product? Am I missing something?


@yjoura
Replies

PanagiotisCharalampous
23 Mar 2018, 09:10

Hi yjoura,

The current plan is to release visual backtesting in cTrader Desktop v3.01. Stay tuned!

Best Regards,

Panagiotis


@PanagiotisCharalampous

MaRCHeW
23 Mar 2018, 10:14

RE:

Fantastic info. Thanks Panagiotis :)

Panagiotis Charalampous said:

Hi yjoura,

The current plan is to release visual backtesting in cTrader Desktop v3.01. Stay tuned!

Best Regards,

Panagiotis

 


@MaRCHeW

abotrader
08 Oct 2018, 23:05

HI,

My cAlgo version 3.03 is freezing in visual testing when i add this code :

        void OnPositionOpened(PositionOpenedEventArgs args)
        {
            if (RunningMode != RunningMode.Optimization)
            {
                Chart.DrawVerticalLine(Guid.NewGuid().ToString(), args.Position.EntryTime, (args.Position.TradeType == TradeType.Buy ? Color.Red : Color.Blue));
                Chart.DrawText(Guid.NewGuid().ToString(), "Opened " + args.Position.TradeType, args.Position.EntryTime, args.Position.EntryPrice, Color.White);
            }
        }

 


@abotrader

PanagiotisCharalampous
09 Oct 2018, 09:59

Hi aboukerker,

Can you please share the complete cBot code so that we can reproduce the issue?

Best Regards,

Panagiotis


@PanagiotisCharalampous

abotrader
09 Oct 2018, 20:50

using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class MACD_PSAR_STOCH : Robot
    {
        const string Label = "MACD_PSAR_STOCH";

        [Parameter(DefaultValue = 1, Step = 1, MaxValue = 1, MinValue = 1)]
        public int MaxTrades { get; set; }

        [Parameter(DefaultValue = 70, Step = 1, MaxValue = 300, MinValue = 70)]
        public double TakeProfit { get; set; }

        [Parameter(DefaultValue = 300, Step = 1, MaxValue = 350, MinValue = 70)]
        public double StopLoss { get; set; }

        // MACD
        [Parameter(DefaultValue = 26, Step = 1, MaxValue = 50, MinValue = 1)]
        public int LongCycle { get; set; }

        [Parameter(DefaultValue = 14, Step = 1, MaxValue = 30, MinValue = 1)]
        public int ShortCycle { get; set; }

        [Parameter(DefaultValue = 9, Step = 1, MaxValue = 50, MinValue = 1)]
        public int Period { get; set; }

        // Stochastic
        [Parameter(DefaultValue = 14, Step = 1, MaxValue = 50, MinValue = 1)]
        public int Kperiod { get; set; }

        [Parameter(DefaultValue = 3, Step = 1, MaxValue = 50, MinValue = 1)]
        public int KSlowing { get; set; }

        [Parameter(DefaultValue = 9, Step = 1, MaxValue = 50, MinValue = 1)]
        public int Dperiod { get; set; }

        [Parameter(DefaultValue = 2, Step = 1)]
        public int RiskPercent { get; set; }

        [Parameter(DefaultValue = 10, Step = 10)]
        public int Volume { get; set; }

        [Parameter(DefaultValue = MovingAverageType.Simple)]
        public MovingAverageType MAType { get; set; }

        MacdCrossOver macd;
        ParabolicSAR sar;
        StochasticOscillator stoch;

        protected override void OnStart()
        {
            Positions.Opened += OnPositionOpened;
            Positions.Closed += OnPositionClosed;
            macd = Indicators.MacdCrossOver(MarketSeries.Close, LongCycle, ShortCycle, Period);
            sar = Indicators.ParabolicSAR(0.02, 0.2);
            stoch = Indicators.StochasticOscillator(Kperiod, KSlowing, Dperiod, MAType);
        }

        protected override void OnTick()
        {
            double Bid = Symbol.Bid;
            double Ask = Symbol.Ask;
            double Point = Symbol.TickSize;
            if (sar.Result.Last(1) > Bid && macd.MACD.IsRising() && macd.MACD.HasCrossedAbove(macd.Signal, 0) && (stoch.PercentK.Last(0) < 35 || (stoch.PercentK.HasCrossedAbove(stoch.PercentD, 0) && stoch.PercentK.IsRising())))
            {
                ClosePositions(TradeType.Sell);
                if (Check())
                {
                    ExecuteMarketOrder(TradeType.Buy, Symbol, CalculateVolume(), Label, StopLoss, TakeProfit);
                }
            }
            else if (sar.Result.Last(1) < Ask && macd.MACD.IsFalling() && macd.MACD.HasCrossedBelow(macd.Signal, 0) && (stoch.PercentK.Last(0) > 60 || (stoch.PercentD.HasCrossedAbove(stoch.PercentK, 0) && stoch.PercentD.IsRising())))
            {
                ClosePositions(TradeType.Buy);
                if (Check())
                {
                    ExecuteMarketOrder(TradeType.Sell, Symbol, CalculateVolume(), Label, StopLoss, TakeProfit);
                }
            }
        }
          protected override void OnStop()
        {
            if (IsBacktesting)
            {
                foreach (var pos in Positions.FindAll(Label, Symbol))
                {
                    ClosePosition(pos);
                }
            }
        }

        void OnPositionOpened(PositionOpenedEventArgs args)
        {
            if (RunningMode != RunningMode.Optimization)
            {
                Chart.DrawVerticalLine(Guid.NewGuid().ToString(), args.Position.EntryTime, (args.Position.TradeType == TradeType.Buy ? Color.Red : Color.Blue));
                //Chart.DrawText(Guid.NewGuid().ToString(), "Opened " + args.Position.TradeType, args.Position.EntryTime, args.Position.EntryPrice, Color.White);
            }
        }

        void OnPositionClosed(PositionClosedEventArgs args)
        {

        }


        double CalculateVolume()
        {
            double _volume = 0;
            if (Volume == 0)
            {
                // Our total balance is our account balance plus any reserve funds. We do not always keep all our money in the trading account.
                double totalBalance = Account.Balance / MaxTrades;

                // Calculate the total risk allowed per trade.
                double riskPerTrade = (totalBalance * RiskPercent) / 100;
                // Add the stop loss, commission pips and spread to get the total pips used for the volume calculation.
                double totalPips = StopLoss + Symbol.Spread + 0.8;
                // CommissionPips
                // Calculate the exact volume to be traded. Then round the volume to the nearest 100,000 and convert to an int so that it can be returned to the caller.
                _volume = Math.Round(riskPerTrade / (Symbol.PipValue * totalPips), 2);

            }
            else
            {
                _volume = Volume;
            }
            return Symbol.NormalizeVolumeInUnits(_volume);
        }

        int NumberOfOpenOrders()
        {
            return Positions.FindAll(Label, Symbol).Length;
        }

        bool Check()
        {

            bool result = true;
            if (NumberOfOpenOrders() >= MaxTrades)
            {
                result = false;
            }
            else if (Account.MarginLevel != null && Account.MarginLevel < 130)
            {
                string msg = String.Format("{0} Check => Equity {1} MarginLevel {2} ", Server.Time, Account.Equity, Account.MarginLevel);
                Print(msg);
                result = false;
            }
            return result;
        }

        void ClosePositions(TradeType tradeType)
        {
            foreach (var position in Positions.FindAll(Label, Symbol, tradeType))
            {
                ClosePosition(position);
            }
        }

        double NormalizePrice(double d)
        {
            return Math.Round(d, Symbol.Digits);
        }

        protected override void OnError(Error error)
        {
            Print("Error Code : {0} ", error.Code);
            if (error.Code == ErrorCode.NoMoney)
                Stop();
        }
    }
}

parameter !

 

[ChartParameters]
Symbol = MICROSOFT
Timeframe = m1

[cBotParameters]
MaxTrades = 1
TakeProfit = 178
StopLoss = 235
LongCycle = 17
ShortCycle = 5
Period = 15
Kperiod = 11
KSlowing = 38
Dperiod = 20
RiskPercent = 2
Volume = 1
MAType = TimeSeries


@abotrader

PanagiotisCharalampous
10 Oct 2018, 10:11

Hi aboukerker,

I could not reproduce any issue. Visual backtesting seems to be working fine. Can you make sure that this is not caused because of the speed setting?

Best Regards,

Panagiotis


@PanagiotisCharalampous

abotrader
10 Oct 2018, 14:25

Please retry with this method 


        void OnPositionOpened(PositionOpenedEventArgs args)
        {
            if (RunningMode != RunningMode.Optimization)
            {
                Chart.DrawVerticalLine(Guid.NewGuid().ToString(), args.Position.EntryTime, (args.Position.TradeType == TradeType.Buy ? Color.Red : Color.Blue));
                Chart.DrawText(Guid.NewGuid().ToString(), "Opened " + args.Position.TradeType, args.Position.EntryTime, args.Position.EntryPrice, Color.White);
            }
        }

 


@abotrader

PanagiotisCharalampous
11 Oct 2018, 10:58

Hi aboukerker,

That works fine as well. Is it possible to make a short video with your issue and send it to us?

Best Regards,

Panagiotis


@PanagiotisCharalampous