Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

Broker Friendly Orders with Brakets

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Broker Friendly Orders with Brakets

    Is this the Best way to send Target / Stop OCO order to an entry for external brokers like Rithmic or others?
    The code also count if a target is hit as a win and the profits in currency

    Code:
        
    
    private Order entryOrder=null;
    private Order targetOrder = null;
    private Order stopOrder = null;
    private Order flattenOrder = null;
    private int sumFilledFlatten=0;
    private int sumFilledEntry=0;
    private int sumFilledTarget = 0;
    private int sumFilledStop = 0;
    
    private void OnExecutionUpdate(object sender, ExecutionEventArgs e)
            {
                if (flattenOrder != null && flattenOrder  == e.Execution.Order){
                    sumFilledFlatten += e.Execution.Quantity;
                    Log(String.Format("Flatten Order Execution: {0} on Account {1} ({2}/{3})",e.Execution.Quantity, currentAccount.Name, account_index, accountNumber),LogLevel.Information);
    
                    if(sumFilledFlatten==c){
                        Log(String.Format("Flatten Filled: {0} on Account {1} ({2}/{3})",sumFilledFlatten, currentAccount.Name, account_index, accountNumber),LogLevel.Information);
                          sumFilledFlatten=0;
                        flattenOrder=null;
                    }
                }
    
                if (entryOrder != null && entryOrder  == e.Execution.Order){
    
                    sumFilledEntry += e.Execution.Quantity;
    
                    Log(String.Format("Entry Order Execution: {0} on Account {1} ({2}/{3})",e.Execution.Quantity, currentAccount.Name, account_index, accountNumber),LogLevel.Information);
    
                            if (EntryPrices.IsNullOrEmpty())
                      EntryPrices = new List<double>();
    
                  for (int i = 0; i < e.Execution.Quantity; i++)
                      EntryPrices.Add(e.Execution.Price);
    
                  // Now we can calculate the average entry price, and use it to protect the specifc entry
                  double averageEntryPrice = 0;
                  for (int i = 0; i < EntryPrices.Count; i++)
                      averageEntryPrice += EntryPrices[i];
                  averageEntryPrice /= EntryPrices.Count;
    
                    enterPrice = averageEntryPrice;
                     if (stopOrder == null && targetOrder == null)
                      {
                           if (e.Execution.Order.OrderAction == OrderAction.Buy){
                               string oco2 = Guid.NewGuid().ToString("N");
    
                                targetOrder = currentAccount.CreateOrder(Instrument,OrderAction.Sell,OrderType.Limit,TimeInForce.Day,sumFilledEntry,averageEntryPrice+tp,0,oco2,"Target",null);
                                stopOrder = currentAccount.CreateOrder(Instrument,OrderAction.Sell,OrderType.StopMarket,TimeInForce.Day,sumFilledEntry,0,averageEntryPrice-sl,oco2,"StopLoss",null);
                                currentAccount.Submit(new[] {targetOrder, stopOrder});
                           }
                           if (e.Execution.Order.OrderAction == OrderAction.Sell){
                                string oco2 = Guid.NewGuid().ToString("N");
                                targetOrder = currentAccount.CreateOrder(Instrument,OrderAction.Buy,OrderType.Limit,TimeInForce.Day,sumFilledEntry,averageEntryPrice-tp,0,oco2,"Target",null);
                                stopOrder = currentAccount.CreateOrder(Instrument,OrderAction.Buy,OrderType.StopMarket,TimeInForce.Day,sumFilledEntry,0,averageEntryPrice+sl,oco2,"StopLoss",null);
                                currentAccount.Submit(new[] {targetOrder, stopOrder});
    
                           }
    
                           Log(String.Format("Braket Submitted: {0} on Account {1} ({2}/{3})",sumFilledEntry, currentAccount.Name, account_index, accountNumber),LogLevel.Information);
    
                     }
                      else
                       {
    
                         stopOrder.QuantityChanged = sumFilledEntry;
                         targetOrder.QuantityChanged = sumFilledEntry;
                         if (e.Execution.Order.OrderAction == OrderAction.Buy){
                             stopOrder.StopPriceChanged  = averageEntryPrice-sl;
                             targetOrder.LimitPriceChanged = averageEntryPrice+tp;
                         }
                         if (e.Execution.Order.OrderAction == OrderAction.Sell){
                             stopOrder.StopPriceChanged  = averageEntryPrice+sl;
                             targetOrder.LimitPriceChanged = averageEntryPrice-tp;
                         }
                         currentAccount.Change(new[] {stopOrder, targetOrder});
                           Log(String.Format("Braket Changed: {0} on Account {1} ({2}/{3})",sumFilledEntry, currentAccount.Name, account_index, accountNumber),LogLevel.Information);
                       }
                    if (sumFilledEntry == c)
                      {
                          // Move to Class?
                        Log(String.Format("Entry Filled: {0} on Account {1} ({2}/{3})",sumFilledEntry, currentAccount.Name, account_index, accountNumber),LogLevel.Information);
    
                          sumFilledEntry = 0;
                          EntryPrices.Clear();
                        entryOrder=null;
                            }
    
    
                }
    
                 if (stopOrder != null && stopOrder == e.Execution.Order)
                      {
    
                       sumFilledStop+= e.Execution.Quantity;
                       Log(String.Format("StopLoss Order Execution: {0} on Account {1} ({2}/{3})",e.Execution.Quantity, currentAccount.Name, account_index, accountNumber),LogLevel.Information);
                          if (sumFilledStop == c)
                          {
    
    
                             Log(String.Format("Trade Profit Counted on Account {0} ({1}/{2})", currentAccount.Name, account_index, accountNumber),LogLevel.Information);
                        double profits = (e.Execution.Price - enterPrice )*e.Execution.Quantity*Instrument.MasterInstrument.PointValue*enterDir;                    
                        dailyDrawDown+=-profits;
                        dailyProfits+=profits;
                        StratProfits+=profits;                    
                        if(dailyDrawDown<0)dailyDrawDown=0;
                        enterDir=0;    
                        dailyLosses++;
                        inTrade=false;
    
    
                        stopOrder=null;
                        argetOrder=null;
    
                            Log(String.Format("StopLoss Filled: {0} on Account {1} ({2}/{3})",sumFilledStop, currentAccount.Name, account_index, accountNumber),LogLevel.Information);
                            Log(String.Format("Losses: {0} on Account {1} ({2}/{3})",dailyLosses, currentAccount.Name, account_index, accountNumber),LogLevel.Information);
    
                        sumFilledStop = 0;
                          }
                      }
    
                   if (targetOrder != null && targetOrder == e.Execution.Order)
                   {
                        sumFilledTarget+= e.Execution.Quantity;
                        Log(String.Format("Target Order Execution: {0} on Account {1} ({2}/{3})",e.Execution.Quantity, currentAccount.Name, account_index, accountNumber),LogLevel.Information);
    
                        if (sumFilledTarget == c)
                        {
    
    
                             Log(String.Format("Trade Profit Counted on Account {0} ({1}/{2})", currentAccount.Name, account_index, accountNumber),LogLevel.Information);
                        double profits = (e.Execution.Price - enterPrice )*e.Execution.Quantity*Instrument.MasterInstrument.PointValue*enterDir;                    
                        dailyDrawDown+=-profits;
                        dailyProfits+=profits;
                        StratProfits+=profits;                    
                        if(dailyDrawDown<0)dailyDrawDown=0;
                        enterDir=0;    
                        dailyWins++;
                        inTrade=false;
    
                        stopOrder=null;
                        targetOrder=null;
    
                           Log(String.Format("Target Filled: {0} on Account {1} ({2}/{3})",sumFilledTarget, currentAccount.Name, account_index, accountNumber),LogLevel.Information);
                           Log(String.Format("Wins: {0} on Account {1} ({2}/{3})",dailyWins, currentAccount.Name, account_index, accountNumber),LogLevel.Information);
    
                         sumFilledTarget=0;
                          }
                   }
    
    
            }
        ​
    Last edited by Pole123; 08-23-2023, 05:34 AM.

    #2
    Hello Pole123,

    Thank you for your post.

    The key with brokers such as Rithmic and Interactive Brokers is that Order, Execution, and Position events are not sent through in a specific order. With that in mind, you should not rely on Order information in OnExecutionUpdate. With that in mind, it is better to use execution.Name rather than execution.Order in case the execution update is sent prior to an order update for a partial fill, for example. We have a snippet "Using Execution information to calculate Average Entry Price (Rithmic/Interactive Brokers Friendly Approach)" on the OnExecutionUpdate() help guide page here:That said, since you are using the Account class, it is very similar to the unmanaged approach for a strategy. I suggest reviewing the RithmicIBFriendlyExamples at the link below, especially the UnmanagedRithmicIBFriendlyExample, as that will be most similar to what you are looking to achieve with stop/target orders tied together with OCO:Please let us know if we may be of further assistance.

    Comment

    Latest Posts

    Collapse

    Topics Statistics Last Post
    Started by NullPointStrategies, Today, 05:17 AM
    0 responses
    41 views
    0 likes
    Last Post NullPointStrategies  
    Started by argusthome, 03-08-2026, 10:06 AM
    0 responses
    124 views
    0 likes
    Last Post argusthome  
    Started by NabilKhattabi, 03-06-2026, 11:18 AM
    0 responses
    64 views
    0 likes
    Last Post NabilKhattabi  
    Started by Deep42, 03-06-2026, 12:28 AM
    0 responses
    41 views
    0 likes
    Last Post Deep42
    by Deep42
     
    Started by TheRealMorford, 03-05-2026, 06:15 PM
    0 responses
    46 views
    0 likes
    Last Post TheRealMorford  
    Working...
    X