Sample Robot with Multiple Positions

admin's avatar

admin since: 30 Nov -0001;

  05 Oct 2012, 19:56
Sample Robot with Multiple Positions

UPDATED

This code is a reference to handling multiple positions. This robot is intended to be used as an example and does not guarantee any particular outcome or profit of any kind.

using cAlgo.API;
using cAlgo.API.Indicators;

namespace cAlgo.Robots
{
    [Robot]
    public class SampleMultiplePositions : Robot
    {
        private MovingAverage _fastMa;
        private MovingAverage _slowMa;

        [Parameter(DefaultValue = "Sample cBot")]
        public string cBotLabel { get; set; }

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

        [Parameter("MA Type")]
        public MovingAverageType MAType { get; set; }

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

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

        [Parameter(DefaultValue = 100000)]
        public int Volume { get; set; }

        [Parameter("Stop Loss (pips)", DefaultValue = 100)]
        public int StopLoss { get; set; }

        [Parameter("Take Profit (pips)", DefaultValue = 100)]
        public int TakeProfit { get; set; }

        [Parameter("Trigger (pips)", DefaultValue = 10)]
        public int Trigger { get; set; }

        [Parameter("Trailing Stop (pips)", DefaultValue = 10)]
        public int TrailingStop { get; set; }


        [Parameter("MinBalance", DefaultValue = 5000)]
        public double MinBalance { get; set; }

        [Parameter("MinLoss", DefaultValue = -200.0)]
        public double MinLoss { get; set; }

        [Parameter(DefaultValue = 3)]
        public int MaxPositions { get; set; }


        protected override void OnStart()
        {
            _fastMa = Indicators.MovingAverage(SourceSeries, FastPeriods, MAType);
            _slowMa = Indicators.MovingAverage(SourceSeries, SlowPeriods, MAType);

            Positions.Opened += PositionsOnOpened;
            Positions.Closed += PositionsOnClosed;
        }

        protected override void OnBar()
        {
            var cBotPositions = Positions.FindAll(cBotLabel);

            if (cBotPositions.Length > MaxPositions) return;

            var currentSlowMa = _slowMa.Result.Last(0);
            var currentFastMa = _fastMa.Result.Last(0);

            var previousSlowMa = _slowMa.Result.Last(1);
            var previousFastMa = _fastMa.Result.Last(1);

            // Condition to Buy
            if (previousSlowMa > previousFastMa && currentSlowMa <= currentFastMa)
                ExecuteMarketOrder(TradeType.Buy, Symbol, Volume, cBotLabel, StopLoss, TakeProfit);
            else if (previousSlowMa < previousFastMa && currentSlowMa >= currentFastMa)
                ExecuteMarketOrder(TradeType.Sell, Symbol, Volume, cBotLabel, StopLoss, TakeProfit);

            // Some condition to close all positions
            if (Account.Balance < MinBalance)
                foreach (var position in cBotPositions)
                    ClosePosition(position);

            // Some condition to close one position
            foreach (var position in cBotPositions)
                if (position.GrossProfit < MinLoss)
                    ClosePosition(position);

            // Trailing Stop for all positions
            SetTrailingStop();
        }

        private void PositionsOnOpened(PositionOpenedEventArgs obj)
        {
            Position openedPosition = obj.Position;
            if (openedPosition.Label != cBotLabel) return;

            Print("position opened at {0}", openedPosition.EntryPrice);
        }

        private void PositionsOnClosed(PositionClosedEventArgs obj)
        {
            Position closedPosition = obj.Position;
            if (closedPosition.Label != cBotLabel) return;

            Print("position closed with {0} gross profit", closedPosition.GrossProfit);
        }


        /// <summary>
        /// When the profit in pips is above or equal to Trigger the stop loss will start trailing the spot price.
        /// TrailingStop defines the number of pips the Stop Loss trails the spot price by. 
        /// If Trigger is 0 trailing will begin immediately. 
        /// </summary>
        private void SetTrailingStop()
        {
            var sellPositions = Positions.FindAll(cBotLabel, Symbol, TradeType.Sell);

            foreach (Position position in sellPositions)
            {
                double distance = position.EntryPrice - Symbol.Ask;

                if (distance < Trigger*Symbol.PipSize) continue;

                double newStopLossPrice = Symbol.Ask + TrailingStop*Symbol.PipSize;

                if (position.StopLoss == null || newStopLossPrice < position.StopLoss)
                    ModifyPosition(position, newStopLossPrice, position.TakeProfit);
            }

            var buyPositions = Positions.FindAll(cBotLabel, Symbol, TradeType.Buy);

            foreach (Position position in buyPositions)
            {
                double distance = Symbol.Bid - position.EntryPrice;

                if (distance < Trigger*Symbol.PipSize) continue;

                double newStopLossPrice = Symbol.Bid - TrailingStop*Symbol.PipSize;
                if (position.StopLoss == null || newStopLossPrice > position.StopLoss)
                    ModifyPosition(position, newStopLossPrice, position.TakeProfit);
            }
        }
    }
}
TRADERS FIRST™

cerana since: 10 Oct 2012;

  30 Oct 2012, 11:24
RE:
admin said:

namespace cAlgo.Robots { [Robot] public class SampleMultiplePositions : Robot { private readonly List _listPosition = new List();

 

 

Error: Using the generic type 'System.Collections.Generic. List<T>' requires 1 type arguments
admin's avatar

admin since: 30 Nov -0001;

  20 Nov 2012, 17:36

It should be:

private readonly List<Position> _listPosition = new List<Position>();

TRADERS FIRST™

cerana since: 10 Oct 2012;

  24 Nov 2012, 20:59

Thank you!

Matej_Bajec since: 25 Aug 2015;

  07 Nov 2015, 16:55

Hi,

can somebody help with this robot.

I would like to add to it - in case robot finds all criteria met and open a position (buy or a sell) to open another position in case same criteria re-appear again but first position did not yet reach ST or TP.

//+------------------------------------------------------------------+
//+                           Code generated using FxPro Quant 2.1.2 |
//+------------------------------------------------------------------+

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


namespace cAlgo.Robots
{
   [Robot(TimeZone = TimeZones.UTC)]
   public class Prototype : Robot
   {


      //Global declaration
      private StochasticOscillator i_Stochastic_Main;
      private StochasticOscillator i_Stochastic_Signal;
      double _Stochastic_Main;
      double _Stochastic_Signal;
      bool _AND_1;
      bool _AND;

DateTime LastTradeExecution = new DateTime(0);

      protected override void OnStart()
      {
         i_Stochastic_Main=Indicators.StochasticOscillator(10,3,10,MovingAverageType.Simple);
         i_Stochastic_Signal=Indicators.StochasticOscillator(10,3,10,MovingAverageType.Simple);

      }

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

         //Local declaration
         TriState _Sell = new TriState();
         TriState _Buy = new TriState();

         //Step 1
         _Stochastic_Main = i_Stochastic_Main.PercentK.Last(0);
         _Stochastic_Signal = i_Stochastic_Signal.PercentD.Last(0);

         //Step 2

         //Step 3
         _AND_1 = ((_Stochastic_Signal <= 20) && 
   (_Stochastic_Main <= 10));
         _AND = ((_Stochastic_Signal >= 80) && 
   (_Stochastic_Main >= 90));

         //Step 4
            if( _AND ) _Sell = _OpenPosition(0,true,Symbol.Code,TradeType.Sell,0.1,0,1500,250,""); 
            if( _AND_1 ) _Buy = _OpenPosition(0,true,Symbol.Code,TradeType.Buy,0.1,0,1500,250,""); 

      }

bool NoOrders(string symbolCode, double[] magicIndecies){if (symbolCode == "")symbolCode = Symbol.Code;string[] labels = new string[magicIndecies.Length];for (int i = 0; i < magicIndecies.Length; i++){labels[i] = "FxProQuant_" + magicIndecies[i].ToString("F0");}foreach (Position pos in Positions){if (pos.SymbolCode != symbolCode)continue;if (labels.Length == 0)return false;foreach (var label in labels){if (pos.Label == label)return false;}}foreach (PendingOrder po in PendingOrders){if (po.SymbolCode != symbolCode)continue;if (labels.Length == 0)return false;foreach (var label in labels){if (po.Label == label)return false;}}return true;}

TriState _OpenPosition(double magicIndex, bool noOrders, string symbolCode, TradeType tradeType, double lots, double slippage, double? stopLoss, double? takeProfit, string comment){Symbol symbol = (Symbol.Code == symbolCode) ? Symbol : MarketData.GetSymbol(symbolCode);if (noOrders && Positions.Find("FxProQuant_" + magicIndex.ToString("F0"), symbol) != null)return new TriState();if (stopLoss < 1)stopLoss = null;if (takeProfit < 1)takeProfit=null;if(symbol.Digits==5||symbol.Digits == 3){if (stopLoss != null)stopLoss /= 10;if (takeProfit != null)takeProfit /= 10;slippage /= 10;}int volume = Convert.ToInt32(lots * 100000);if (!ExecuteMarketOrder(tradeType, symbol, volume, "FxProQuant_" + magicIndex.ToString("F0"), stopLoss, takeProfit, slippage, comment).IsSuccessful){Thread.Sleep(400);return false;}return true;}

TriState _SendPending(double magicIndex, bool noOrders, string symbolCode, PendingOrderType poType, TradeType tradeType, double lots, int priceAction, double priceValue, double? stopLoss, double? takeProfit,DateTime? expiration, string comment){Symbol symbol = (Symbol.Code == symbolCode) ? Symbol : MarketData.GetSymbol(symbolCode);if (noOrders && PendingOrders.__Find("FxProQuant_" + magicIndex.ToString("F0"), symbol) != null)return new TriState();if (stopLoss < 1)stopLoss = null;if (takeProfit < 1)takeProfit = null;if (symbol.Digits == 5 || symbol.Digits == 3){if (stopLoss != null)stopLoss /= 10;if (takeProfit != null)takeProfit /= 10;}int volume = Convert.ToInt32(lots * 100000);double targetPrice;switch (priceAction){case 0:targetPrice = priceValue;break;case 1:targetPrice = symbol.Bid - priceValue * symbol.TickSize;break;case 2:targetPrice = symbol.Bid + priceValue * symbol.TickSize;break;case 3:targetPrice = symbol.Ask - priceValue * symbol.TickSize;break;case 4:targetPrice = symbol.Ask + priceValue * symbol.TickSize;break;default:targetPrice = priceValue;break;}if (expiration.HasValue && (expiration.Value.Ticks == 0 || expiration.Value == DateTime.Parse("1970.01.01 00:00:00")))expiration = null;if (poType == PendingOrderType.Limit){if (!PlaceLimitOrder(tradeType, symbol, volume, targetPrice, "FxProQuant_" + magicIndex.ToString("F0"), stopLoss, takeProfit, expiration, comment).IsSuccessful){Thread.Sleep(400);return false;}return true;}else if (poType == PendingOrderType.Stop){if (!PlaceStopOrder(tradeType, symbol, volume, targetPrice, "FxProQuant_" + magicIndex.ToString("F0"), stopLoss, takeProfit, expiration, comment).IsSuccessful){Thread.Sleep(400);return false;}return true;}return new TriState();}

TriState _ModifyPosition(double magicIndex, string symbolCode, int slAction, double slValue, int tpAction, double tpValue){Symbol symbol = (Symbol.Code == symbolCode) ? Symbol : MarketData.GetSymbol(symbolCode);var pos = Positions.Find("FxProQuant_" + magicIndex.ToString("F0"), symbol);if (pos == null)return new TriState();double? sl, tp;if (slValue == 0)sl = null;else{switch (slAction){case 0:sl = pos.StopLoss;break;case 1:if (pos.TradeType == TradeType.Buy)sl = pos.EntryPrice - slValue * symbol.TickSize;else sl = pos.EntryPrice + slValue * symbol.TickSize;break;case 2:sl = slValue;break;default:sl = pos.StopLoss;break;}}if (tpValue == 0)tp = null;else{switch (tpAction){case 0:tp = pos.TakeProfit;break;case 1:if (pos.TradeType == TradeType.Buy)tp = pos.EntryPrice + tpValue * symbol.TickSize;else tp = pos.EntryPrice - tpValue * symbol.TickSize;break;case 2:tp = tpValue;break;default:tp = pos.TakeProfit;break;}}if (!ModifyPosition(pos, sl, tp).IsSuccessful){Thread.Sleep(400);return false;}return true;}

TriState _ModifyPending(double magicIndex, string symbolCode, int slAction, double slValue, int tpAction, double tpValue, int priceAction, double priceValue, int expirationAction, DateTime? expiration){Symbol symbol = (Symbol.Code == symbolCode) ? Symbol : MarketData.GetSymbol(symbolCode);var po = PendingOrders.__Find("FxProQuant_" + magicIndex.ToString("F0"), symbol);if (po == null)return new TriState();double targetPrice;double? sl, tp;if (slValue == 0)sl = null;else{switch (slAction){case 0:sl = po.StopLoss;break;case 1:if (po.TradeType == TradeType.Buy)sl = po.TargetPrice - slValue * symbol.TickSize;else sl = po.TargetPrice + slValue * symbol.TickSize;break;case 2:sl = slValue;break;default:sl = po.StopLoss;break;}}if (tpValue == 0)tp = null;else{switch (tpAction){case 0:tp = po.TakeProfit;break;case 1:if (po.TradeType == TradeType.Buy)tp = po.TargetPrice + tpValue * symbol.TickSize;else tp = po.TargetPrice - tpValue * symbol.TickSize;break;case 2:tp = tpValue;break;default:tp = po.TakeProfit;break;}}switch (priceAction){case 0:targetPrice = po.TargetPrice;break;case 1:targetPrice = priceValue;break;case 2:targetPrice = po.TargetPrice + priceValue * symbol.TickSize;break;case 3:targetPrice = po.TargetPrice - priceValue * symbol.TickSize;break;case 4:targetPrice = symbol.Bid - priceValue * symbol.TickSize;break;case 5:targetPrice = symbol.Bid + priceValue * symbol.TickSize;break;case 6:targetPrice = symbol.Ask - priceValue * symbol.TickSize;break;case 7:targetPrice = symbol.Ask + priceValue * symbol.TickSize;break;default:targetPrice = po.TargetPrice;break;}if (expiration.HasValue && (expiration.Value.Ticks == 0 || expiration.Value == DateTime.Parse("1970.01.01 00:00:00")))expiration = null;if (expirationAction == 0)expiration = po.ExpirationTime;if (!ModifyPendingOrder(po, targetPrice, sl, tp, expiration).IsSuccessful){Thread.Sleep(400);return false;}return true;}

TriState _ClosePosition(double magicIndex, string symbolCode, double lots){Symbol symbol = (Symbol.Code == symbolCode) ? Symbol : MarketData.GetSymbol(symbolCode);var pos = Positions.Find("FxProQuant_" + magicIndex.ToString("F0"), symbol);if (pos == null)return new TriState();TradeResult result;if (lots == 0){result = ClosePosition(pos);}else{int volume = Convert.ToInt32(lots * 100000);result = ClosePosition(pos, volume);}if (!result.IsSuccessful){Thread.Sleep(400);return false;}return true;}

TriState _DeletePending(double magicIndex, string symbolCode){Symbol symbol = (Symbol.Code == symbolCode)?Symbol:MarketData.GetSymbol(symbolCode);var po=PendingOrders.__Find("FxProQuant_" + magicIndex.ToString("F0"), symbol);if (po == null)return new TriState();if (!CancelPendingOrder(po).IsSuccessful){Thread.Sleep(400);return false;}return true;}

bool _OrderStatus(double magicIndex, string symbolCode, int test){Symbol symbol=(Symbol.Code==symbolCode)?Symbol:MarketData.GetSymbol(symbolCode);var pos=Positions.Find("FxProQuant_" + magicIndex.ToString("F0"), symbol);if (pos != null){if (test == 0)return true;if (test == 1)return true;if (test == 3)return pos.TradeType == TradeType.Buy;if (test == 4)return pos.TradeType == TradeType.Sell;}var po = PendingOrders.__Find("FxProQuant_" + magicIndex.ToString("F0"), symbol);if (po != null){if (test == 0)return true;if (test == 2)return true;if (test == 3)return po.TradeType == TradeType.Buy;if (test == 4)return po.TradeType == TradeType.Sell;if (test == 5)return po.OrderType == PendingOrderType.Limit;if (test == 6)return po.OrderType == PendingOrderType.Stop;}return false;}

int TimeframeToInt(TimeFrame tf){if(tf == TimeFrame.Minute) return 1;else if (tf == TimeFrame.Minute2) return 2;else if (tf == TimeFrame.Minute3) return 3;else if (tf == TimeFrame.Minute4) return 4;else if (tf == TimeFrame.Minute5) return 5;else if (tf == TimeFrame.Minute10) return 10;else if (tf == TimeFrame.Minute15) return 15;else if (tf == TimeFrame.Minute30) return 30;else if (tf == TimeFrame.Hour) return 60;else if (tf == TimeFrame.Hour4) return 240;else if (tf == TimeFrame.Daily) return 1440;else if (tf == TimeFrame.Weekly) return 10080;else if (tf == TimeFrame.Monthly) return 43200;return 1;}   
}
}

public struct TriState{public static readonly TriState NonExecution = new TriState(0);public static readonly TriState False = new TriState(-1);public static readonly TriState True = new TriState(1);sbyte value;TriState(int value){this.value = (sbyte)value;}public bool IsNonExecution{get { return value == 0; }}public static implicit operator TriState(bool x){return x ? True : False;}public static TriState operator ==(TriState x, TriState y){if (x.value == 0 || y.value == 0)return NonExecution;return x.value == y.value ? True : False;}public static TriState operator !=(TriState x, TriState y){if (x.value == 0 || y.value == 0)return NonExecution;return x.value != y.value ? True : False;}public static TriState operator !(TriState x){return new TriState(-x.value);}public static TriState operator &(TriState x, TriState y){return new TriState(x.value < y.value ? x.value : y.value);}public static TriState operator |(TriState x, TriState y){return new TriState(x.value > y.value ? x.value : y.value);}public static bool operator true(TriState x){return x.value > 0;}public static bool operator false(TriState x){return x.value < 0;}public static implicit operator bool(TriState x){return x.value > 0;}public override bool Equals(object obj){if (!(obj is TriState))return false;return value == ((TriState)obj).value;}public override int GetHashCode(){return value;}public override string ToString(){if (value > 0)return "True";if (value < 0)return "False";return "NonExecution";}}

public static class PendingEx{public static PendingOrder __Find(this cAlgo.API.PendingOrders pendingOrders, string label, Symbol symbol){foreach (PendingOrder po in pendingOrders){if (po.SymbolCode == symbol.Code && po.Label == label)return po;}return null;}}

Matej_Bajec since: 25 Aug 2015;

  07 Nov 2015, 16:57
//+------------------------------------------------------------------+
//+                           Code generated using FxPro Quant 2.1.2 |
//+------------------------------------------------------------------+

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


namespace cAlgo.Robots
{
   [Robot(TimeZone = TimeZones.UTC)]
   public class Prototype : Robot
   {


      //Global declaration
      private StochasticOscillator i_Stochastic_Main;
      private StochasticOscillator i_Stochastic_Signal;
      double _Stochastic_Main;
      double _Stochastic_Signal;
      bool _AND_1;
      bool _AND;

DateTime LastTradeExecution = new DateTime(0);

      protected override void OnStart()
      {
         i_Stochastic_Main=Indicators.StochasticOscillator(10,3,10,MovingAverageType.Simple);
         i_Stochastic_Signal=Indicators.StochasticOscillator(10,3,10,MovingAverageType.Simple);

      }

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

         //Local declaration
         TriState _Sell = new TriState();
         TriState _Buy = new TriState();

         //Step 1
         _Stochastic_Main = i_Stochastic_Main.PercentK.Last(0);
         _Stochastic_Signal = i_Stochastic_Signal.PercentD.Last(0);

         //Step 2

         //Step 3
         _AND_1 = ((_Stochastic_Signal <= 20) && 
   (_Stochastic_Main <= 10));
         _AND = ((_Stochastic_Signal >= 80) && 
   (_Stochastic_Main >= 90));

         //Step 4
            if( _AND ) _Sell = _OpenPosition(0,true,Symbol.Code,TradeType.Sell,0.1,0,1500,250,""); 
            if( _AND_1 ) _Buy = _OpenPosition(0,true,Symbol.Code,TradeType.Buy,0.1,0,1500,250,""); 

      }

bool NoOrders(string symbolCode, double[] magicIndecies){if (symbolCode == "")symbolCode = Symbol.Code;string[] labels = new string[magicIndecies.Length];for (int i = 0; i < magicIndecies.Length; i++){labels[i] = "FxProQuant_" + magicIndecies[i].ToString("F0");}foreach (Position pos in Positions){if (pos.SymbolCode != symbolCode)continue;if (labels.Length == 0)return false;foreach (var label in labels){if (pos.Label == label)return false;}}foreach (PendingOrder po in PendingOrders){if (po.SymbolCode != symbolCode)continue;if (labels.Length == 0)return false;foreach (var label in labels){if (po.Label == label)return false;}}return true;}

TriState _OpenPosition(double magicIndex, bool noOrders, string symbolCode, TradeType tradeType, double lots, double slippage, double? stopLoss, double? takeProfit, string comment){Symbol symbol = (Symbol.Code == symbolCode) ? Symbol : MarketData.GetSymbol(symbolCode);if (noOrders && Positions.Find("FxProQuant_" + magicIndex.ToString("F0"), symbol) != null)return new TriState();if (stopLoss < 1)stopLoss = null;if (takeProfit < 1)takeProfit=null;if(symbol.Digits==5||symbol.Digits == 3){if (stopLoss != null)stopLoss /= 10;if (takeProfit != null)takeProfit /= 10;slippage /= 10;}int volume = Convert.ToInt32(lots * 100000);if (!ExecuteMarketOrder(tradeType, symbol, volume, "FxProQuant_" + magicIndex.ToString("F0"), stopLoss, takeProfit, slippage, comment).IsSuccessful){Thread.Sleep(400);return false;}return true;}

TriState _SendPending(double magicIndex, bool noOrders, string symbolCode, PendingOrderType poType, TradeType tradeType, double lots, int priceAction, double priceValue, double? stopLoss, double? takeProfit,DateTime? expiration, string comment){Symbol symbol = (Symbol.Code == symbolCode) ? Symbol : MarketData.GetSymbol(symbolCode);if (noOrders && PendingOrders.__Find("FxProQuant_" + magicIndex.ToString("F0"), symbol) != null)return new TriState();if (stopLoss < 1)stopLoss = null;if (takeProfit < 1)takeProfit = null;if (symbol.Digits == 5 || symbol.Digits == 3){if (stopLoss != null)stopLoss /= 10;if (takeProfit != null)takeProfit /= 10;}int volume = Convert.ToInt32(lots * 100000);double targetPrice;switch (priceAction){case 0:targetPrice = priceValue;break;case 1:targetPrice = symbol.Bid - priceValue * symbol.TickSize;break;case 2:targetPrice = symbol.Bid + priceValue * symbol.TickSize;break;case 3:targetPrice = symbol.Ask - priceValue * symbol.TickSize;break;case 4:targetPrice = symbol.Ask + priceValue * symbol.TickSize;break;default:targetPrice = priceValue;break;}if (expiration.HasValue && (expiration.Value.Ticks == 0 || expiration.Value == DateTime.Parse("1970.01.01 00:00:00")))expiration = null;if (poType == PendingOrderType.Limit){if (!PlaceLimitOrder(tradeType, symbol, volume, targetPrice, "FxProQuant_" + magicIndex.ToString("F0"), stopLoss, takeProfit, expiration, comment).IsSuccessful){Thread.Sleep(400);return false;}return true;}else if (poType == PendingOrderType.Stop){if (!PlaceStopOrder(tradeType, symbol, volume, targetPrice, "FxProQuant_" + magicIndex.ToString("F0"), stopLoss, takeProfit, expiration, comment).IsSuccessful){Thread.Sleep(400);return false;}return true;}return new TriState();}

TriState _ModifyPosition(double magicIndex, string symbolCode, int slAction, double slValue, int tpAction, double tpValue){Symbol symbol = (Symbol.Code == symbolCode) ? Symbol : MarketData.GetSymbol(symbolCode);var pos = Positions.Find("FxProQuant_" + magicIndex.ToString("F0"), symbol);if (pos == null)return new TriState();double? sl, tp;if (slValue == 0)sl = null;else{switch (slAction){case 0:sl = pos.StopLoss;break;case 1:if (pos.TradeType == TradeType.Buy)sl = pos.EntryPrice - slValue * symbol.TickSize;else sl = pos.EntryPrice + slValue * symbol.TickSize;break;case 2:sl = slValue;break;default:sl = pos.StopLoss;break;}}if (tpValue == 0)tp = null;else{switch (tpAction){case 0:tp = pos.TakeProfit;break;case 1:if (pos.TradeType == TradeType.Buy)tp = pos.EntryPrice + tpValue * symbol.TickSize;else tp = pos.EntryPrice - tpValue * symbol.TickSize;break;case 2:tp = tpValue;break;default:tp = pos.TakeProfit;break;}}if (!ModifyPosition(pos, sl, tp).IsSuccessful){Thread.Sleep(400);return false;}return true;}

TriState _ModifyPending(double magicIndex, string symbolCode, int slAction, double slValue, int tpAction, double tpValue, int priceAction, double priceValue, int expirationAction, DateTime? expiration){Symbol symbol = (Symbol.Code == symbolCode) ? Symbol : MarketData.GetSymbol(symbolCode);var po = PendingOrders.__Find("FxProQuant_" + magicIndex.ToString("F0"), symbol);if (po == null)return new TriState();double targetPrice;double? sl, tp;if (slValue == 0)sl = null;else{switch (slAction){case 0:sl = po.StopLoss;break;case 1:if (po.TradeType == TradeType.Buy)sl = po.TargetPrice - slValue * symbol.TickSize;else sl = po.TargetPrice + slValue * symbol.TickSize;break;case 2:sl = slValue;break;default:sl = po.StopLoss;break;}}if (tpValue == 0)tp = null;else{switch (tpAction){case 0:tp = po.TakeProfit;break;case 1:if (po.TradeType == TradeType.Buy)tp = po.TargetPrice + tpValue * symbol.TickSize;else tp = po.TargetPrice - tpValue * symbol.TickSize;break;case 2:tp = tpValue;break;default:tp = po.TakeProfit;break;}}switch (priceAction){case 0:targetPrice = po.TargetPrice;break;case 1:targetPrice = priceValue;break;case 2:targetPrice = po.TargetPrice + priceValue * symbol.TickSize;break;case 3:targetPrice = po.TargetPrice - priceValue * symbol.TickSize;break;case 4:targetPrice = symbol.Bid - priceValue * symbol.TickSize;break;case 5:targetPrice = symbol.Bid + priceValue * symbol.TickSize;break;case 6:targetPrice = symbol.Ask - priceValue * symbol.TickSize;break;case 7:targetPrice = symbol.Ask + priceValue * symbol.TickSize;break;default:targetPrice = po.TargetPrice;break;}if (expiration.HasValue && (expiration.Value.Ticks == 0 || expiration.Value == DateTime.Parse("1970.01.01 00:00:00")))expiration = null;if (expirationAction == 0)expiration = po.ExpirationTime;if (!ModifyPendingOrder(po, targetPrice, sl, tp, expiration).IsSuccessful){Thread.Sleep(400);return false;}return true;}

TriState _ClosePosition(double magicIndex, string symbolCode, double lots){Symbol symbol = (Symbol.Code == symbolCode) ? Symbol : MarketData.GetSymbol(symbolCode);var pos = Positions.Find("FxProQuant_" + magicIndex.ToString("F0"), symbol);if (pos == null)return new TriState();TradeResult result;if (lots == 0){result = ClosePosition(pos);}else{int volume = Convert.ToInt32(lots * 100000);result = ClosePosition(pos, volume);}if (!result.IsSuccessful){Thread.Sleep(400);return false;}return true;}

TriState _DeletePending(double magicIndex, string symbolCode){Symbol symbol = (Symbol.Code == symbolCode)?Symbol:MarketData.GetSymbol(symbolCode);var po=PendingOrders.__Find("FxProQuant_" + magicIndex.ToString("F0"), symbol);if (po == null)return new TriState();if (!CancelPendingOrder(po).IsSuccessful){Thread.Sleep(400);return false;}return true;}

bool _OrderStatus(double magicIndex, string symbolCode, int test){Symbol symbol=(Symbol.Code==symbolCode)?Symbol:MarketData.GetSymbol(symbolCode);var pos=Positions.Find("FxProQuant_" + magicIndex.ToString("F0"), symbol);if (pos != null){if (test == 0)return true;if (test == 1)return true;if (test == 3)return pos.TradeType == TradeType.Buy;if (test == 4)return pos.TradeType == TradeType.Sell;}var po = PendingOrders.__Find("FxProQuant_" + magicIndex.ToString("F0"), symbol);if (po != null){if (test == 0)return true;if (test == 2)return true;if (test == 3)return po.TradeType == TradeType.Buy;if (test == 4)return po.TradeType == TradeType.Sell;if (test == 5)return po.OrderType == PendingOrderType.Limit;if (test == 6)return po.OrderType == PendingOrderType.Stop;}return false;}

int TimeframeToInt(TimeFrame tf){if(tf == TimeFrame.Minute) return 1;else if (tf == TimeFrame.Minute2) return 2;else if (tf == TimeFrame.Minute3) return 3;else if (tf == TimeFrame.Minute4) return 4;else if (tf == TimeFrame.Minute5) return 5;else if (tf == TimeFrame.Minute10) return 10;else if (tf == TimeFrame.Minute15) return 15;else if (tf == TimeFrame.Minute30) return 30;else if (tf == TimeFrame.Hour) return 60;else if (tf == TimeFrame.Hour4) return 240;else if (tf == TimeFrame.Daily) return 1440;else if (tf == TimeFrame.Weekly) return 10080;else if (tf == TimeFrame.Monthly) return 43200;return 1;}   
}
}

public struct TriState{public static readonly TriState NonExecution = new TriState(0);public static readonly TriState False = new TriState(-1);public static readonly TriState True = new TriState(1);sbyte value;TriState(int value){this.value = (sbyte)value;}public bool IsNonExecution{get { return value == 0; }}public static implicit operator TriState(bool x){return x ? True : False;}public static TriState operator ==(TriState x, TriState y){if (x.value == 0 || y.value == 0)return NonExecution;return x.value == y.value ? True : False;}public static TriState operator !=(TriState x, TriState y){if (x.value == 0 || y.value == 0)return NonExecution;return x.value != y.value ? True : False;}public static TriState operator !(TriState x){return new TriState(-x.value);}public static TriState operator &(TriState x, TriState y){return new TriState(x.value < y.value ? x.value : y.value);}public static TriState operator |(TriState x, TriState y){return new TriState(x.value > y.value ? x.value : y.value);}public static bool operator true(TriState x){return x.value > 0;}public static bool operator false(TriState x){return x.value < 0;}public static implicit operator bool(TriState x){return x.value > 0;}public override bool Equals(object obj){if (!(obj is TriState))return false;return value == ((TriState)obj).value;}public override int GetHashCode(){return value;}public override string ToString(){if (value > 0)return "True";if (value < 0)return "False";return "NonExecution";}}

public static class PendingEx{public static PendingOrder __Find(this cAlgo.API.PendingOrders pendingOrders, string label, Symbol symbol){foreach (PendingOrder po in pendingOrders){if (po.SymbolCode == symbol.Code && po.Label == label)return po;}return null;}}
jani's avatar

jani since: 05 Apr 2019;

  07 Nov 2019, 01:40
RE:

admin said:

UPDATED

This code is a reference to handling multiple positions. This robot is intended to be used as an example and does not guarantee any particular outcome or profit of any kind.

using cAlgo.API;
using cAlgo.API.Indicators;

namespace cAlgo.Robots
{
    [Robot]
    public class SampleMultiplePositions : Robot
    {
        private MovingAverage _fastMa;
        private MovingAverage _slowMa;

        [Parameter(DefaultValue = "Sample cBot")]
        public string cBotLabel { get; set; }

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

        [Parameter("MA Type")]
        public MovingAverageType MAType { get; set; }

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

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

        [Parameter(DefaultValue = 100000)]
        public int Volume { get; set; }

        [Parameter("Stop Loss (pips)", DefaultValue = 100)]
        public int StopLoss { get; set; }

        [Parameter("Take Profit (pips)", DefaultValue = 100)]
        public int TakeProfit { get; set; }

        [Parameter("Trigger (pips)", DefaultValue = 10)]
        public int Trigger { get; set; }

        [Parameter("Trailing Stop (pips)", DefaultValue = 10)]
        public int TrailingStop { get; set; }


        [Parameter("MinBalance", DefaultValue = 5000)]
        public double MinBalance { get; set; }

        [Parameter("MinLoss", DefaultValue = -200.0)]
        public double MinLoss { get; set; }

        [Parameter(DefaultValue = 3)]
        public int MaxPositions { get; set; }


        protected override void OnStart()
        {
            _fastMa = Indicators.MovingAverage(SourceSeries, FastPeriods, MAType);
            _slowMa = Indicators.MovingAverage(SourceSeries, SlowPeriods, MAType);

            Positions.Opened += PositionsOnOpened;
            Positions.Closed += PositionsOnClosed;
        }

        protected override void OnBar()
        {
            var cBotPositions = Positions.FindAll(cBotLabel);

            if (cBotPositions.Length > MaxPositions) return;

            var currentSlowMa = _slowMa.Result.Last(0);
            var currentFastMa = _fastMa.Result.Last(0);

            var previousSlowMa = _slowMa.Result.Last(1);
            var previousFastMa = _fastMa.Result.Last(1);

            // Condition to Buy
            if (previousSlowMa > previousFastMa && currentSlowMa <= currentFastMa)
                ExecuteMarketOrder(TradeType.Buy, Symbol, Volume, cBotLabel, StopLoss, TakeProfit);
            else if (previousSlowMa < previousFastMa && currentSlowMa >= currentFastMa)
                ExecuteMarketOrder(TradeType.Sell, Symbol, Volume, cBotLabel, StopLoss, TakeProfit);

            // Some condition to close all positions
            if (Account.Balance < MinBalance)
                foreach (var position in cBotPositions)
                    ClosePosition(position);

            // Some condition to close one position
            foreach (var position in cBotPositions)
                if (position.GrossProfit < MinLoss)
                    ClosePosition(position);

            // Trailing Stop for all positions
            SetTrailingStop();
        }

        private void PositionsOnOpened(PositionOpenedEventArgs obj)
        {
            Position openedPosition = obj.Position;
            if (openedPosition.Label != cBotLabel) return;

            Print("position opened at {0}", openedPosition.EntryPrice);
        }

        private void PositionsOnClosed(PositionClosedEventArgs obj)
        {
            Position closedPosition = obj.Position;
            if (closedPosition.Label != cBotLabel) return;

            Print("position closed with {0} gross profit", closedPosition.GrossProfit);
        }


        /// <summary>
        /// When the profit in pips is above or equal to Trigger the stop loss will start trailing the spot price.
        /// TrailingStop defines the number of pips the Stop Loss trails the spot price by. 
        /// If Trigger is 0 trailing will begin immediately. 
        /// </summary>
        private void SetTrailingStop()
        {
            var sellPositions = Positions.FindAll(cBotLabel, Symbol, TradeType.Sell);

            foreach (Position position in sellPositions)
            {
                double distance = position.EntryPrice - Symbol.Ask;

                if (distance < Trigger*Symbol.PipSize) continue;

                double newStopLossPrice = Symbol.Ask + TrailingStop*Symbol.PipSize;

                if (position.StopLoss == null || newStopLossPrice < position.StopLoss)
                    ModifyPosition(position, newStopLossPrice, position.TakeProfit);
            }

            var buyPositions = Positions.FindAll(cBotLabel, Symbol, TradeType.Buy);

            foreach (Position position in buyPositions)
            {
                double distance = Symbol.Bid - position.EntryPrice;

                if (distance < Trigger*Symbol.PipSize) continue;

                double newStopLossPrice = Symbol.Bid - TrailingStop*Symbol.PipSize;
                if (position.StopLoss == null || newStopLossPrice > position.StopLoss)
                    ModifyPosition(position, newStopLossPrice, position.TakeProfit);
            }
        }
    }
}

Correction to this code, if you want only one opened position when MaxPositions is set to 1 you should put:

if (cBotPositions.Length >= MaxPositions) return;

NOT

if (cBotPositions.Length > MaxPositions) return;

Above will give you 2 open positions for MaxPosition value 1

“Markets can remain irrational longer than you can remain solvent.” ― John Maynard Keynes // https://www.youtube.com/watch?v=8GP87dgTqF8