Replies

danblackadder
11 Nov 2019, 14:03

BUMP. Multi-symbol support in back testing when? I have been waiting over 2 years for this... 


@danblackadder

danblackadder
30 Sep 2018, 18:45

Hi,

I see we can still not use  MarketData.GetSymbol in backtesting.

Is there any plans to update this in the future as I understand it has been sat in your request pile for the last 2 years.

Thanks,

Dan


@danblackadder

danblackadder
20 Sep 2017, 00:37

Incase anyone else wants to use this in their own way, I found a fix:

            var volumeAvailable = (riskPercentage * Account.Balance) * Symbol.PreciseLeverage;

            var volumeToTrade = volumeAvailable % 1000 >= 500 ? volumeAvailable + 1000 - volumeAvailable % 1000 : volumeAvailable - volumeAvailable % 1000;

            if (volumeToTrade > Symbol.VolumeMin)
            {

                ExecuteMarketOrder(tradeType, Symbol, Convert.ToInt64(volumeToTrade), "Position", Symbol.Spread, null);

            }
            else
            {

                ExecuteMarketOrder(tradeType, Symbol, Symbol.VolumeMin, "Position");

            }

By checking if the current volumeAvailable modulo is bigger than 500, it will round up, and if it isn't it will round down. The rounding is complete by adding the difference between 1000 and the remainder, or simply removing the remainder. 

 

In a bot (the Risk reference is set to 0.01 for 1% 0.05 for 5% 0.10 for 10% or 1 for 100%, meaning you would be willing to risk 100% of your capital to open 1 single trade. If you only risk 0.01 (1%) then you are able to open 100 trades before you run out of capital.

// -------------------------------------------------------------------------------------------------
//
//    This code is a cAlgo API sample.
//
//    This cBot is intended to be used as a sample and does not guarantee any particular outcome or
//    profit of any kind. Use it at your own risk.
//
//    The "Sample Trend cBot" will buy when fast period moving average crosses the slow period moving average and sell when 
//    the fast period moving average crosses the slow period moving average. The orders are closed when an opposite signal 
//    is generated. There can only by one Buy or Sell order at any time.
//
// -------------------------------------------------------------------------------------------------

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

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class SampleTrendcBot : Robot
    {
        [Parameter("MA Type")]
        public MovingAverageType MAType { get; set; }

        [Parameter()]
        public DataSeries SourceSeries { get; set; }

        [Parameter("Slow Periods", DefaultValue = 10)]
        public int SlowPeriods { get; set; }

        [Parameter("Fast Periods", DefaultValue = 5)]
        public int FastPeriods { get; set; }

        [Parameter("Risk", DefaultValue = 0.01, MinValue = 0.01, MaxValue = 1, Step = 0.01)]
        public double risk { get; set; }

        private MovingAverage slowMa;
        private MovingAverage fastMa;
        private const string label = "Position";

        protected override void OnStart()
        {
            fastMa = Indicators.MovingAverage(SourceSeries, FastPeriods, MAType);
            slowMa = Indicators.MovingAverage(SourceSeries, SlowPeriods, MAType);
        }

        protected override void OnTick()
        {
            var longPosition = Positions.Find(label, Symbol, TradeType.Buy);
            var shortPosition = Positions.Find(label, Symbol, TradeType.Sell);

            var currentSlowMa = slowMa.Result.Last(0);
            var currentFastMa = fastMa.Result.Last(0);
            var previousSlowMa = slowMa.Result.Last(1);
            var previousFastMa = fastMa.Result.Last(1);

            if (previousSlowMa > previousFastMa && currentSlowMa <= currentFastMa && longPosition == null)
            {


                if (shortPosition != null)
                {

                    Close(TradeType.Sell);

                }

                Open(TradeType.Buy);

            }
            else if (previousSlowMa < previousFastMa && currentSlowMa >= currentFastMa && shortPosition == null)
            {

                if (longPosition != null)
                {

                    Close(TradeType.Buy);

                }

                Open(TradeType.Sell);

            }

        }

        private void Close(TradeType tradeType)
        {

            foreach (var position in Positions.FindAll(label, Symbol, tradeType))
                ClosePosition(position);

        }

        private void Open(TradeType tradeType)
        {

            var volumeAvailable = (riskPercentage * Account.Balance) * Symbol.PreciseLeverage;

            var volumeToTrade = volumeAvailable % 1000 >= 500 ? volumeAvailable + 1000 - volumeAvailable % 1000 : volumeAvailable - volumeAvailable % 1000;

            if (volumeToTrade > Symbol.VolumeMin)
            {

                ExecuteMarketOrder(tradeType, Symbol, Convert.ToInt64(volumeToTrade), "Position", Symbol.Spread, null);

            }
            else
            {

                ExecuteMarketOrder(tradeType, Symbol, Symbol.VolumeMin, "Position");

            }

        }
    }
}

 


@danblackadder

danblackadder
19 Sep 2017, 11:34

Hi,

Okay, that makes sense. So I should just be able to round to a number divisible with the Symbol.VolumeStep.

I will try to fix this tonight and report back if I have done incase anyone else wants to use the same script.

Thanks!

Dan


@danblackadder

danblackadder
18 Sep 2017, 23:48

Hi,

Thanks for your reply.

Apologies, it probably doesn't make sense because I was using 2 seperate variables, when they should have been 1 and the same. I had to change the code since due to the errors that were occuring.

 

My code also uses a custom indicators, so I have copied it over to a basic cBot for you.

In the below, if you leave it in its current state, it will make 1 trade. If you change the volume to a set figure, it will work as intended.

// -------------------------------------------------------------------------------------------------
//
//    This code is a cAlgo API sample.
//
//    This cBot is intended to be used as a sample and does not guarantee any particular outcome or
//    profit of any kind. Use it at your own risk.
//
//    The "Sample Trend cBot" will buy when fast period moving average crosses the slow period moving average and sell when 
//    the fast period moving average crosses the slow period moving average. The orders are closed when an opposite signal 
//    is generated. There can only by one Buy or Sell order at any time.
//
// -------------------------------------------------------------------------------------------------

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

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class SampleTrendcBot : Robot
    {
        [Parameter("MA Type")]
        public MovingAverageType MAType { get; set; }

        [Parameter()]
        public DataSeries SourceSeries { get; set; }

        [Parameter("Slow Periods", DefaultValue = 10)]
        public int SlowPeriods { get; set; }

        [Parameter("Fast Periods", DefaultValue = 5)]
        public int FastPeriods { get; set; }

        [Parameter("Risk", DefaultValue = 0.01, MinValue = 0.01, MaxValue = 100, Step = 0.01)]
        public double risk { get; set; }

        private MovingAverage slowMa;
        private MovingAverage fastMa;
        private const string label = "Position";

        protected override void OnStart()
        {
            fastMa = Indicators.MovingAverage(SourceSeries, FastPeriods, MAType);
            slowMa = Indicators.MovingAverage(SourceSeries, SlowPeriods, MAType);
        }

        protected override void OnTick()
        {
            var longPosition = Positions.Find(label, Symbol, TradeType.Buy);
            var shortPosition = Positions.Find(label, Symbol, TradeType.Sell);

            var currentSlowMa = slowMa.Result.Last(0);
            var currentFastMa = fastMa.Result.Last(0);
            var previousSlowMa = slowMa.Result.Last(1);
            var previousFastMa = fastMa.Result.Last(1);

            if (previousSlowMa > previousFastMa && currentSlowMa <= currentFastMa && longPosition == null)
            {


                if (shortPosition != null)
                {

                    Close(TradeType.Sell);

                }

                Open(TradeType.Buy);

            }
            else if (previousSlowMa < previousFastMa && currentSlowMa >= currentFastMa && shortPosition == null)
            {

                if (longPosition != null)
                {

                    Close(TradeType.Buy);

                }

                Open(TradeType.Sell);

            }

        }

        private void Close(TradeType tradeType)
        {

            foreach (var position in Positions.FindAll(label, Symbol, tradeType))
                ClosePosition(position);

        }

        private void Open(TradeType tradeType)
        {

            var volumeToTrade = (risk * Account.Balance) * Symbol.PreciseLeverage;
            //var volumeToTrade = 1000;

            if (volumeToTrade > Symbol.VolumeMin)
            {

                ExecuteMarketOrder(tradeType, Symbol, Convert.ToInt64(volumeToTrade), label);

            }
            else
            {

                ExecuteMarketOrder(tradeType, Symbol, Symbol.VolumeMin, label);

            }

        }
    }
}

Thank you for you time.


@danblackadder