Cancel Pending orders after a maximum number of orders is filled (Issue)

Created at 02 Jan 2023, 04:42
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!
CT

ctid2434759

Joined 02.08.2022

Cancel Pending orders after a maximum number of orders is filled (Issue)
02 Jan 2023, 04:42


Hi there,

I've written a bot that is supposed to cancel all pending orders if the maximum open order size is reached.


However, when two pending orders fill at the exact same time the logic does not operate and the extra orders will fill resulting in too many orders being filled.

I need to make sure that under no circumstance more than three orders are filled/open at the same time.
Is this possible?

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;

namespace cAlgo.Robots
{
    [Robot(AccessRights = AccessRights.None)]
    public class CUSTOMCBOT : Robot
    {
        [Parameter(DefaultValue = 0.0)]
        public string Message { get; set; }

        // Maximum number of open orders allowed
        private const int MaxPositions = 3;


        protected override void OnStart()
        {

        Positions.Opened += PositionsOnOpened; 
        
        // These two orders will fill straight away
        // Bringing MaxPositions = 2
        ExecuteMarketOrder(TradeType.Buy, SymbolName, 10000, "marketOrder1", 10, 10); 
        ExecuteMarketOrder(TradeType.Buy, SymbolName, 10000, "marketOrder2", 10, 10); 
        
        // Get the current price of the pairs last high.
        // Just for easier testing purposes
        var currentPrice = MarketData.GetBars(TimeFrame.Minute).LastBar.High; 

        // Place two orders at the same price to see if they will both fill or one will cancel at the maximum of 3 orders.
        // These two will fill at the same time but only one should fill because we will be at MaxPositions = 3.
        // However it causes an error when they try to fill at the same time and end up both filling taking MaxPositions = 4 which is above the cutoff level.
        PlaceLimitOrder(TradeType.Buy, SymbolName, 2000, currentPrice - 0.1 * Symbol.PipSize, "0.1", null, 10);
        PlaceLimitOrder(TradeType.Buy, SymbolName, 2000, currentPrice - 0.1 * Symbol.PipSize, "0.1", null, 10);
        
        // These always cancel as long as they don't try to fill at the same time also.
        // Which should not happen given they are at a different price level
        PlaceLimitOrder(TradeType.Buy, SymbolName, 2000, currentPrice - 1 * Symbol.PipSize, "1", null, 10);
        PlaceLimitOrder(TradeType.Buy, SymbolName, 2000, currentPrice - 2 * Symbol.PipSize, "2", null, 10);
     
        
        }

        protected override void OnTick()
        {

        }
        
      
        // method is called when a position opens. 
        private void PositionsOnOpened(PositionOpenedEventArgs args)
        {
            var pos = args.Position;
            Print("Position opened at {0}", pos.EntryPrice);
            
            // Handle order updates here
            // Check if the maximum number of open orders has been reached
            if (Positions.Count >= MaxPositions)
            {
                Print("MORE THAN 3 POSITIONS");
                foreach (var order in PendingOrders)
                {
                    CancelPendingOrderAsync(order);
                }
                // Do not send the order if the maximum number of open orders has been reached
                return;

            }
                           
            Print("LESS THAN 3 POSITIONS");                         
            
        }
        


        protected override void OnStop()
        {
            // Handle cBot stop here
        }
        

        
    }
}

 


@ctid2434759
Replies

PanagiotisCharalampous
02 Jan 2023, 09:39

Hi there,

You could consider using market range orders instead of limit orders. Limit orders are on the server so your check will only execute after the orders have opened positions. If you need full control, you need to run everything on your side.

Aieden Technologies

Need help? Join us on Telegram

Need premium support? Trade with us

 


@PanagiotisCharalampous

ctid2434759
03 Jan 2023, 00:22

RE:

Hi Panagiotis,

Thanks for that.

I wasn't aware of Market Range Orders I'll have a look into it.

Curiously do you know of a way to 'step in front' of the server so they never execute? 
Or is your solution of market range orders the only one you can think of?

I just need my account to never fill more than 'X' orders. 2, 4, 3 ect.
So if I have 24 LMT orders waiting, only fill 3 then stop filling anymore.

Thanks.
If I can't figure it out I might end up hiring your services.


@ctid2434759

ctid2434759
03 Jan 2023, 01:27

RE: RE:

Hi Panagiotis,

 

I had a play with Market Range Orders, however they do not function in the desired way.

It seems to grab the current 'Ask' price and not fill a buy order any higher than 'x' pips to allow for slippage.
So current Ask of 0.68023 for AUDUSD with a range of 2 pips cannot fill higher than 0.68043.

I need to have LMT buy orders bellow the current price waiting to get filled.

There is a current mechanism in cTrader that stops more orders being filled when you go over the allowed account leverage.

So if I have 24 orders, 3 might fill then I will get a msg saying no more can fill due to insufficient funds (max leverage) which is great.
I need to utilise that mechanism but for amount of trades.

So same mechanism but just never fill more than 2 or 3 trades using LMT buy orders.
It's like I need an account/server level max open positions.


Any guidance would be greatly appreciated, I've written the rest of the bot but it's just this one thing that is a make or break that I can't solve.


Thanks

 


@ctid2434759

PanagiotisChar
03 Jan 2023, 09:21

Hi there,

Curiously do you know of a way to 'step in front' of the server so they never execute? 

There is no such way unfortunately.

Aieden Technologies

Need help? Join us on Telegram

Need premium support? Trade with us

 


@PanagiotisChar

ctid2434759
04 Jan 2023, 00:24 ( Updated at: 04 Jan 2023, 00:26 )

RE:

Thanks for your help Panagiotis.

I actually figured out how to utilise your suggestion of ExecuteMarketRangeOrder using it like it was a LMT order.

I'll paste the code bellow if anyone needs it.

Essentially you get a specific price on the chart bellow the current price 'X' pips. Save that value and draw a line if you want for visual reference.
Then keep checking current ASK price on tick and if that price goes bellow your 'Line' then it executes a MarketRangeOrder.

You can change the values to suit and change the CheckPositions call if you want to add more orders etc.

Thanks again.

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.SingaporeStandardTime, AccessRights = AccessRights.None)]
    public class ClosePositionOnTime : Robot
    
    
    // NOTE
    // For the live environment i need to change the _highprice = Bars.HighPrices.Maximum(2);
    // Change it to _highprice = Bars.LastBar.High;
    // It has to do with the way the close of the markets works.
    
    {

        // Just the current simulator pairs global variables.
        private double _highPrice;
        private double _lmtPrice;


        protected override void OnStart()
        {
            
             // Get the high Price of the last candle for this pair
            _highPrice = Bars.HighPrices.Maximum(2);
            // Then set the price 1 pip bellow that (so i can allow it to act like a LMT order)
            _lmtPrice = _highPrice - 1 * Symbol.PipSize;
            
            // Draw this LMT order or price line on the chart so i can see the entry point.
            var highLine = Chart.DrawHorizontalLine("Low", _lmtPrice, Color.Blue);
            highLine.IsInteractive = true;    

            
        }

  
       protected override void OnTick()
       {           
 
            // Get the current Price, which is the symbols previous ASK price.
            // Then inside the onTick method this keeps checking every tick if the ask price is bellow the entry price.
            var _previousAsk = Symbol.Ask;
            

            
            // Check if the current price is higher than the previous ticks ASK price
            if (_lmtPrice != 0 && _previousAsk < _lmtPrice)
            {
            
                //See if there are any Open positions
                var CheckPositions = Positions.Count;    
               
                
                
                    
                //var myLabelCount = Positions.Count(p => p.Label == "X");
                var currentSymbolOrderLabel = Positions.FindAll("X").Length;
                    
                //If "CheckPositions" Reports That less than 2 total positions are open and no existing current order with the label "X" is open, Then ExecuteMarketRangeOrder
                if (CheckPositions < 2 && currentSymbolOrderLabel < 1) {   
            
                    // Place a buy order
                    // At the current ask price because its bellow the trigger price with a range of 1 pip.
                    ExecuteMarketRangeOrder(TradeType.Buy, SymbolName, 1000, 1, Symbol.Ask, "X", null, 25);
                    //Print("High price: " + _highPrice);   
                    //Print("Current price: " + currentPrice);
                }
            
           }
           
               
                
       }
       


        protected override void OnStop()
        {
            // Handle cBot stop here
        }
    }
}

 


@ctid2434759