Max Draw Down - Stop robot when it reaches certain amount of loss

Created at 13 Apr 2013, 05:25
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!
MA

MANDRIL

Joined 28.03.2013

Max Draw Down - Stop robot when it reaches certain amount of loss
13 Apr 2013, 05:25


Hi,

 

How can i implement in these robot like a Max Draw Down or that it will stop when it reaches x% of the initial account balance?

 

I mean this because this robot doesn't stop still it reaches a profit position so loses can be ilimited and when i tried to add like a stop loss it didn't work very well in the backtesting. 

 

Thanks a lot,

 

 

 

 

using System;
using cAlgo.API;

namespace cAlgo.Robots
{
    [Robot("Robot Forex")]
    public class RobotForex : Robot
    {
        [Parameter(DefaultValue = 10000, MinValue = 10000)]
        public int FirstLot { get; set; }

        [Parameter("Take_Profit", DefaultValue = 180, MinValue = 10)]
        public int TakeProfit { get; set; }
        
        [Parameter("Tral_Start", DefaultValue = 50)]
        public int Tral_Start { get; set; }
        
        [Parameter("Tral_Stop", DefaultValue = 50)]
        public int Tral_Stop { get; set; }

        [Parameter(DefaultValue = 300)]
        public int PipStep { get; set; }

        [Parameter(DefaultValue = 5, MinValue = 2)]
        public int MaxOrders { get; set; }
        
        private Position position;
        private bool RobotStopped;
        private int LotStep=10000;
        
        protected override void OnStart()
        {
            
        }

        protected override void OnTick()
        {
        double Bid=Symbol.Bid;
        double Ask=Symbol.Ask;
        double Point=Symbol.PointSize;      
        
            if(Trade.IsExecuting) return;
            if(Account.Positions.Count > 0 && RobotStopped) return;
            else RobotStopped = false;

            if(Account.Positions.Count == 0) 
                SendFirstOrder(FirstLot);
            else
                ControlSeries();

           foreach (var position in Account.Positions)
            {
                if(position.SymbolCode == Symbol.Code)
                {
                    if(position.TradeType == TradeType.Buy)    
                    {
                    if (Bid-GetAveragePrice(TradeType.Buy)>=Tral_Start*Point)
                    if (Bid-Tral_Stop*Point>=position.StopLoss)
                    Trade.ModifyPosition(position, Bid-Tral_Stop*Point, position.TakeProfit);
                    }
                        
                    if(position.TradeType == TradeType.Sell)    
                    {
                    if (GetAveragePrice(TradeType.Sell)-Ask>=Tral_Start*Point)
                    if (Ask+Tral_Stop*Point<=position.StopLoss || position.StopLoss==0)
                    Trade.ModifyPosition(position, Ask+Tral_Stop*Point, position.TakeProfit);
                    }
                }
             }                
        }

        protected override void OnError(Error CodeOfError)
        {
            if(CodeOfError.Code == ErrorCode.NoMoney)
            {
                RobotStopped = true;
                Print("ERROR!!! No money for order open, robot is stopped!");
            }
            else if(CodeOfError.Code == ErrorCode.BadVolume)
            {
                RobotStopped = true;
                Print("ERROR!!! Bad volume for order open, robot is stopped!");
            }
        }
        
        private void SendFirstOrder(int OrderVolume)
        {
            int Signal = GetStdIlanSignal();
            if(!(Signal < 0))
                switch(Signal)
                {
                    case 0:
                        Trade.CreateBuyMarketOrder(Symbol, OrderVolume);
                    break;
                    case 1:
                        Trade.CreateSellMarketOrder(Symbol, OrderVolume);
                    break;
                }
        }
        
        protected override void OnPositionOpened(Position openedPosition)
        {
            double? StopLossPrice = null;
            double? TakeProfitPrice = null;
            
            if(Account.Positions.Count == 1)
            {
                position = openedPosition;
                if( position.TradeType == TradeType.Buy)
                    TakeProfitPrice = position.EntryPrice + TakeProfit * Symbol.PointSize;
                if( position.TradeType == TradeType.Sell)
                    TakeProfitPrice = position.EntryPrice - TakeProfit * Symbol.PointSize;
            }
            else
                switch(GetPositionsSide())
                {
                    case 0:
                        TakeProfitPrice = GetAveragePrice(TradeType.Buy) + TakeProfit * Symbol.PointSize;
                    break;
                    case 1:
                        TakeProfitPrice = GetAveragePrice(TradeType.Sell) - TakeProfit * Symbol.PointSize;
                    break;
                }

            for(int i = 0; i < Account.Positions.Count; i++)
            {
                position = Account.Positions[i];
                if(StopLossPrice != null || TakeProfitPrice != null)
                    Trade.ModifyPosition(position, position.StopLoss, TakeProfitPrice);
            }
        }

        private double GetAveragePrice(TradeType TypeOfTrade)
        {
            double Result = Symbol.Bid;
            double AveragePrice = 0;
              long Count = 0;

            for(int i = 0; i < Account.Positions.Count; i++)
            {
                position = Account.Positions[i];
                if(position.TradeType == TypeOfTrade)
                   {
                       AveragePrice += position.EntryPrice * position.Volume;
                       Count += position.Volume;
                   }
               }
              if(AveragePrice > 0 && Count > 0)
                Result = AveragePrice / Count;
            return Result;
        }

        private int GetPositionsSide()
        {
            int Result = -1;
            int i, BuySide = 0, SellSide = 0;
            
            for(= 0; i < Account.Positions.Count; i++)
            {
                if(Account.Positions[i].TradeType == TradeType.Buy) BuySide++;
                if(Account.Positions[i].TradeType == TradeType.Sell) SellSide++;
            }
            if(BuySide == Account.Positions.Count) Result = 0;
            if(SellSide == Account.Positions.Count) Result = 1;
            return Result;
        }
        
        private void ControlSeries()
        {
            int _pipstep, NewVolume, Rem;
            int BarCount = 25;
            int Del = MaxOrders - 1;
            
            if(PipStep == 0)
                _pipstep = GetDynamicPipstep(BarCount, Del);
            else
                _pipstep = PipStep;
            
            if(Account.Positions.Count < MaxOrders)
                switch(GetPositionsSide())
                {
                      case 0:
                        if(Symbol.Ask < FindLastPrice(TradeType.Buy) - _pipstep * Symbol.PointSize)
                        {
                            NewVolume = Math.DivRem((int)(FirstLot + FirstLot*Account.Positions.Count), LotStep, out Rem) * LotStep;
                            if(!(NewVolume < LotStep))
                                Trade.CreateBuyMarketOrder(Symbol, NewVolume);
                        }
                       break;
                       case 1:
                        if(Symbol.Bid > FindLastPrice(TradeType.Sell) + _pipstep * Symbol.PointSize)
                        {
                            NewVolume = Math.DivRem((int)(FirstLot + FirstLot*Account.Positions.Count), LotStep, out Rem) * LotStep;
                            if(!(NewVolume < LotStep))
                                Trade.CreateSellMarketOrder(Symbol, NewVolume);
                        }
                       break;
                }
        }
        
        private int GetDynamicPipstep(int CountOfBars, int Del)
        {
            int Result;
            double HighestPrice = 0, LowestPrice = 0;
            int StartBar = MarketSeries.Close.Count - 2 - CountOfBars;
            int EndBar = MarketSeries.Close.Count - 2;
            
            for(int i = StartBar; i < EndBar; i++)
            {
                if(HighestPrice == 0 && LowestPrice == 0)
                {                
                    HighestPrice = MarketSeries.High[i];
                    LowestPrice = MarketSeries.Low[i];
                    continue;
                }
                if(MarketSeries.High[i] > HighestPrice) HighestPrice = MarketSeries.High[i];
                if(MarketSeries.Low[i] < LowestPrice) LowestPrice = MarketSeries.Low[i];
            }
            Result = (int)((HighestPrice - LowestPrice) / Symbol.PointSize / Del);
            return Result;
        }
        
        private double FindLastPrice(TradeType TypeOfTrade)
        {
            double LastPrice = 0;

            for(int i = 0; i < Account.Positions.Count; i++) 
            {
                position = Account.Positions[i];
                if(TypeOfTrade == TradeType.Buy)
                    if(position.TradeType == TypeOfTrade) 
                      {
                           if(LastPrice == 0)
                           {
                               LastPrice = position.EntryPrice;
                               continue;
                           }
                        if(position.EntryPrice < LastPrice)
                              LastPrice = position.EntryPrice;
                      }
                if(TypeOfTrade == TradeType.Sell)
                    if(position.TradeType == TypeOfTrade) 
                      {
                           if(LastPrice == 0)
                           {
                               LastPrice = position.EntryPrice;
                               continue;
                           }
                        if(position.EntryPrice > LastPrice)
                              LastPrice = position.EntryPrice;
                      }
              }
              return LastPrice;
        }
        
        private int GetStdIlanSignal()
        {
            int Result = -1;
            int LastBarIndex = MarketSeries.Close.Count - 2;
            int PrevBarIndex = LastBarIndex - 1;
            
            if(MarketSeries.Close[LastBarIndex] > MarketSeries.Open[LastBarIndex])
                if(MarketSeries.Close[PrevBarIndex] > MarketSeries.Open[PrevBarIndex])
                    Result = 0;
            if(MarketSeries.Close[LastBarIndex] < MarketSeries.Open[LastBarIndex])
                if(MarketSeries.Close[PrevBarIndex] < MarketSeries.Open[PrevBarIndex])
                    Result = 1;
            return Result;
        }
    }
}


@MANDRIL
Replies

MANDRIL
14 Apr 2013, 03:37

Close positions - % original balance

Hi,

Sorry i wanted to say, that i would like to close all the positions when all my trades reach like 90% of the original balance, for example if i start wiht 1000 USD and my trades go against summing -900, and my account goes to 100 USD then automatically close all the positions.

 

Thanks a lot again!!!


@MANDRIL

cAlgo_Fanatic
15 Apr 2013, 11:44

Assign a global field to the starting account balance in the OnStart event.

Then at the beginning of the OnTick event call a method that compares the account equity to that field.

(Assuming that you want to close all account positions, not just the robots. If you want to close only the robots then the code would be different. Please see Labels)

    private double startingBalance;
    private const double BalancePercent = 0.10;

    protected override void OnStart()
    {
        startingBalance = Account.Balance;
    }
    protected override void OnTick()
    {
        CheckBalance();
        //...
    }

    private void CheckBalance()
    {            
        if (Account.Equity <= startingBalance * BalancePercent)
        {
            // close all account positions
            foreach (var pos in Account.Positions)
            {
                Trade.Close(pos);
            }
            Stop(); // Stop the robot
        }
    }




@cAlgo_Fanatic

MANDRIL
16 Apr 2013, 00:47

Thanks a lot!!! You are great!!!! :)


@MANDRIL