Multi-symbol robots and indicators

13 Sep 2013, 12:26Multi-symbol robots and indicators#1
cAlgo_Developmentposts: 125since: 20 Feb 2013

We added new functionality to cAlgo - the ability for robots and indicators to work with multiple symbols. Now it's possible to use multiple symbol prices, OHLCV series and trade different symbols.

 

Requesting symbol

Robots and indicators can request a symbol specifying its symbol code. Symbol objects behave like the default Symbol object of a robot or indicator, containing current Ask, Bid, PipSize and other useful properties.

Symbol symbol = MarketData.GetSymbol("USDJPY");

Print("Symbol: {0}, Ask: {1}, Bid: {2}", symbol.Code, symbol.Ask, symbol.Bid);

 

Requesting OHLCV series

Robots and indicators can request OHLCV series for multiple symbols and timeframes and build indicators based on it.

MarketSeries series = MarketData.GetSeries("EURCAD", TimeFrame.Minute15);
MovingAverage ma = Indicators.SimpleMovingAverage(series.Close, 20);

Print("Symbol: {0}, TimeFrame: {1}", series.SymbolCode, series.TimeFrame);
Print("Last Close: {0}, Average Close: {1}", series.Close.LastValue, ma.Result.LastValue);

 

Trading multiple symbols

Robots in cAlgo can execute orders for different symbols. To do this, the robot must request the needed symbol by its code. Then, it will be possible to use it in a trade request:

 Symbol symbol = MarketData.GetSymbol("GBPCHF");
 ExecuteMarketOrder(TradeType.Buy, symbol, 10000);

The new version of our Demo cTrader and cAlgo is released and can be downloaded from www.spotware.com

Backtesting of Multi-symbol robots in not supported at least for now. It can be implemented in future.


TRADERS FIRST
13 Sep 2013, 12:36Example: Multi-symbol RSI robot#2
cAlgo_Developmentposts: 125since: 20 Feb 2013

Robot below trades EURUSD if both EURUSD and EURJPY are overbought or oversold according to RSI indicator:

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

namespace cAlgo.Robots
{
    [Robot()]
    public class MultiSymbolRsiRobot : Robot
    {

        private const string MyLabel = "MultiSymbolRsiRobot";

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

        [Parameter("Volume", DefaultValue = 10000, MinValue = 1000)]
        public int Volume { get; set; }

        private RelativeStrengthIndex eurJpyRSI;
        private RelativeStrengthIndex eurUsdRSI;

        private Symbol eurUsd;

        protected override void OnStart()
        {
            var eurJpySeries = MarketData.GetSeries("EURJPY", TimeFrame);
            var eurUsdSeries = MarketData.GetSeries("EURUSD", TimeFrame);

            eurJpyRSI = Indicators.RelativeStrengthIndex(eurJpySeries.Close, Periods);
            eurUsdRSI = Indicators.RelativeStrengthIndex(eurUsdSeries.Close, Periods);

            eurUsd = MarketData.GetSymbol("EURUSD");
        }

        protected override void OnTick()
        {
            if (Trade.IsExecuting)
                return;

            if (eurUsdRSI.Result.LastValue > 70 && eurJpyRSI.Result.LastValue > 70)
            {
                ClosePosition(eurUsd, TradeType.Buy);
                OpenPosition(eurUsd, TradeType.Sell);
            }
            if (eurUsdRSI.Result.LastValue < 30 && eurJpyRSI.Result.LastValue < 30)
            {
                ClosePosition(eurUsd, TradeType.Sell);
                OpenPosition(eurUsd, TradeType.Buy);
            }
        }


        private void ClosePosition(Symbol symbol, TradeType tradeType)
        {
            foreach (Position position in Account.Positions)
            {
                if (position.Label == MyLabel && position.SymbolCode == symbol.Code && position.TradeType == tradeType)
                    Trade.Close(position);
            }
        }

        private void OpenPosition(Symbol symbol, TradeType tradeType)
        {
            if (HasPosition(symbol, tradeType))
                return;

            var request = new MarketOrderRequest(tradeType, Volume) 
            {
                Label = MyLabel,
                Symbol = symbol
            };

            Trade.Send(request);
        }

        private bool HasPosition(Symbol symbol, TradeType tradeType)
        {
            foreach (Position position in Account.Positions)
            {
                if (position.SymbolCode == symbol.Code && position.Label == MyLabel && position.TradeType == tradeType)
                    return true;
            }
            return false;
        }

    }
}

 


TRADERS FIRST
19 Sep 2013, 09:01RE: Example: Multi-symbol RSI robot#3
pennyfxposts: 12since: 27 Sep 2012

Does this mean the following code will now return ALL open positions across all pairs ?  If so, this will probably break a lot of Robots.

foreach (Position position in Account.Positions)

19 Sep 2013, 09:15#4
cAlgo_Developmentposts: 125since: 20 Feb 2013

This code was always like this - Account.Positions always contained positions for all symbols.


TRADERS FIRST
19 Sep 2013, 15:13Indicator Example#5
cAlgo_Developmentposts: 125since: 20 Feb 2013

Moving averages of several symbols on a single chart.



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

namespace cAlgo.Indicators
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC)]
    public class MultiSymbolMA : Indicator
    {
        private MovingAverage ma1, ma2, ma3;
        private MarketSeries series1, series2, series3;
        private Symbol symbol1, symbol2, symbol3;

        [Parameter(DefaultValue = "EURUSD")]
        public string Symbol1 { get; set; }

        [Parameter(DefaultValue = "EURAUD")]
        public string Symbol2 { get; set; }

        [Parameter(DefaultValue = "EURCAD")]
        public string Symbol3 { get; set; }

        [Parameter(DefaultValue = 14)]
        public int Period { get; set; }

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

        [Output("MA Symbol 1", Color = Colors.Magenta)]
        public IndicatorDataSeries Result1 { get; set; }

        [Output("MA Symbol 2", Color = Colors.Red)]
        public IndicatorDataSeries Result2 { get; set; }

        [Output("MA Symbol 3", Color = Colors.Yellow)]
        public IndicatorDataSeries Result3 { get; set; }

        protected override void Initialize()
        {
            symbol1 = MarketData.GetSymbol(Symbol1);
            symbol2 = MarketData.GetSymbol(Symbol2);
            symbol3 = MarketData.GetSymbol(Symbol3);

            series1 = MarketData.GetSeries(symbol1, TimeFrame);
            series2 = MarketData.GetSeries(symbol2, TimeFrame);
            series3 = MarketData.GetSeries(symbol3, TimeFrame);

            ma1 = Indicators.MovingAverage(series1.Close, Period, MaType);
            ma2 = Indicators.MovingAverage(series2.Close, Period, MaType);
            ma3 = Indicators.MovingAverage(series3.Close, Period, MaType);
        }

        public override void Calculate(int index)
        {
            ShowOutput(symbol1, Result1, ma1, series1, index);
            ShowOutput(symbol2, Result2, ma2, series2, index);
            ShowOutput(symbol3, Result3, ma3, series3, index);
        }

        private void ShowOutput(Symbol symbol, IndicatorDataSeries result, MovingAverage movingAverage, MarketSeries series, int index)
        {
            int index2 = GetIndexByDate(series, MarketSeries.OpenTime[index]);
            result[index] = movingAverage.Result[index2];

            string text = string.Format("{0} {1}", symbol.Code, Math.Round(result[index], symbol.Digits));

            ChartObjects.DrawText(symbol.Code, text, index + 1, result[index], VerticalAlignment.Center, HorizontalAlignment.Right, Colors.Yellow);
        }

        private int GetIndexByDate(MarketSeries series, DateTime time)
        {
            for (int i = series.Close.Count - 1; i >= 0; i--)
                if (time == series.OpenTime[i])
                    return i;
            return -1;
        }
    }
}

 


TRADERS FIRST
19 Sep 2013, 15:29Indicator Example 2#6
cAlgo_Fanaticposts: 516since: 10 Jan 2013

Multiple symbol information displayed on the chart.

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

namespace cAlgo.Indicators
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC)]
    public class MultiSymbolMarketInfo : Indicator
    {
        private Symbol symbol1;
        private Symbol symbol2;
        private Symbol symbol3;

        [Parameter(DefaultValue = "EURGBP")]
        public string Symbol1 { get; set; }

        [Parameter(DefaultValue = "GBPUSD")]
        public string Symbol2 { get; set; }

        [Parameter(DefaultValue = "EURUSD")]
        public string Symbol3 { get; set; }

        protected override void Initialize()
        {
            symbol1 = MarketData.GetSymbol(Symbol1);
            symbol2 = MarketData.GetSymbol(Symbol2);
            symbol3 = MarketData.GetSymbol(Symbol3);
        }

        public override void Calculate(int index)
        {
            if (!IsLastBar)
                return;

            var text = FormatSymbol(symbol1) + "\n" + FormatSymbol(symbol2) + "\n" + FormatSymbol(symbol3);

            ChartObjects.DrawText("symbol1", text, StaticPosition.TopLeft, Colors.Lime);
        }

        private string FormatSymbol(Symbol symbol)
        {
            var spread = Math.Round(symbol.Spread / symbol.PipSize, 1);
            return string.Format("{0}\t Ask: {1}\t Bid: {2}\t Spread: {3}", symbol.Code, symbol.Ask, symbol.Bid, spread);

        }
    }
}

 


TRADERS FIRST™
19 Sep 2013, 15:46Correlation Coefficient#7
cAlgo_Fanaticposts: 516since: 10 Jan 2013

The correlation coefficient compares how currency pairs have moved in relation to each other.

The correlation coefficient formula is:

using System;
using cAlgo.API;
using cAlgo.API.Internals;

namespace cAlgo.Indicators
{
    [Levels(-1, -0.5, 0, 0.5, 1)]
    [Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, ScalePrecision = 2)]
    public class CorrelationCoefficient : Indicator
    {
        private MarketSeries series2;
        private Symbol symbol2;

        [Parameter(DefaultValue = "EURUSD")]
        public string Symbol2 { get; set; }

        [Parameter(DefaultValue = 22)]
        public int Period { get; set; }

        [Output("Correlation Coefficient", Color = Colors.Yellow)]
        public IndicatorDataSeries Result { get; set; }

        protected override void Initialize()
        {
            symbol2 = MarketData.GetSymbol(Symbol2);
            series2 = MarketData.GetSeries(symbol2, TimeFrame);
        }

        public override void Calculate(int index)
        {
            if (index < Period)
                return;

            double sumX = 0, sumY = 0, sumXY = 0, sumX2 = 0, sumY2 = 0;
            double x, y, x2, y2;

            int index2 = GetIndexByDate(series2, MarketSeries.OpenTime[index]);

            if (index2 == -1)
                return;

            for (int i = 0; i < Period; i++)
            {
                x = MarketSeries.Close[index - i];
                y = series2.Close[index2 - i];

                x2 = x * x;
                y2 = y * y;
                sumX += x;
                sumY += y;
                sumXY += x * y;
                sumX2 += x2;
                sumY2 += y2;
            }

            Result[index] = (Period * (sumXY) - sumX * sumY) / 
                               Math.Sqrt((Period * sumX2 - sumX * sumX) * (Period * sumY2 - sumY * sumY));
        }

        private int GetIndexByDate(MarketSeries series, DateTime time)
        {
            for (int i = series.Close.Count - 1; i >= 0; i--)
            {
                if (time == series.OpenTime[i])
                    return i;
            }
            return -1;
        }
    }
}

 


TRADERS FIRST™
23 Sep 2014, 22:16Multi-symbol robots and indicators#8
Abhiposts: 16since: 31 Aug 2014

Hi Spotware Team, nice improvements. I still cannot run average true range indicator on multiple symbols.

 

Please could you let us know when the feature will be available or if there is a way to get around the problem.

 

Thanks in advance.

 

Regards,

Abhi

24 Sep 2014, 09:56RE: Multi-symbol robots and indicators#9
Spotwareposts: 3329since: 23 Sep 2013

Abhi said:

Hi Spotware Team, nice improvements. I still cannot run average true range indicator on multiple symbols.

 

Please could you let us know when the feature will be available or if there is a way to get around the problem.

 

Thanks in advance.

 

Regards,

Abhi

Please specify what you mean by saying that. You can use multi-symbol data in code of your indicator. You can also add ATR to several charts.


TRADERS FIRST™ Vote for your favorite features: http://vote.spotware.com/
24 Sep 2014, 21:37RE: RE: Multi-symbol robots and indicators#10
Abhiposts: 16since: 31 Aug 2014

Spotware said:

Abhi said:

Hi Spotware Team, nice improvements. I still cannot run average true range indicator on multiple symbols.

 

Please could you let us know when the feature will be available or if there is a way to get around the problem.

 

Thanks in advance.

 

Regards,

Abhi

Please specify what you mean by saying that. You can use multi-symbol data in code of your indicator. You can also add ATR to several charts.

I want to show ATR for multiple symbols on a single chart. The  method call "Indicators.AverageTrueRange(int period , MovingAverageType.Exponential)" can be only called for a single symbol in a chart. Is there anyway to call ATR on multiple symbols and show up on a chart like you showed for RelativeStrengthIndex in this forum on previous posts.

 

Does it make sense now.