Login Page - Create Account

Support Board


Date/Time: Wed, 27 Nov 2024 23:43:18 +0000



Post From: Cancelling multiple orders after 3 bars are added to the chart

[2023-06-29 18:23:02]
User395685 - Posts: 33
Hi,

I would like to code an automated trading study where pending orders are cancelled after 3 new bars are added to the chart. Exactly like at the end of the code below (from tradingsystem.cpp) but for multiple orders, not just one. Each order has to be treated individually and should be cancelled, if unfilled, after 3 bars are added.

In other words:
Order 1 is created at the end of Bar 1, and cancelled at the end of Bar 4 (if unfilled).
Order 2 is created at the end of Bar 2, and cancelled at the end of Bar 5 (if unfilled).
etc...

Is there any simple way to do this?

Thanks for your help.

SCSFExport scsf_TradingExampleOrdersForDifferentSymbolAndAccount(SCStudyInterfaceRef sc)
{
  //Define references to the Subgraphs and Inputs for easy reference
  SCSubgraphRef Subgraph_BuyEntry = sc.Subgraph[0];
  SCSubgraphRef Subgraph_BuyExit = sc.Subgraph[1];
  SCSubgraphRef Subgraph_SellEntry = sc.Subgraph[2];
  SCSubgraphRef Subgraph_SellExit = sc.Subgraph[3];

  SCInputRef Input_Enabled = sc.Input[0];
  SCInputRef Input_ReferenceChartForPrice = sc.Input[1];

  if (sc.SetDefaults)
  {
    // Set the study configuration and defaults.

    sc.GraphName = "Trading Example: Orders for Different Symbol and Account";

    sc.StudyDescription = "This function demonstrates submitting, modifying and canceling an order for a different symbol than the chart the trading study is applied to";

    Subgraph_BuyEntry.Name = "Buy Entry";
    Subgraph_BuyEntry.DrawStyle = DRAWSTYLE_ARROW_UP;
    Subgraph_BuyEntry.PrimaryColor = RGB(0, 255, 0);
    Subgraph_BuyEntry.LineWidth = 2;
    Subgraph_BuyEntry.DrawZeros = false;

    Subgraph_BuyExit.Name = "Buy Exit";
    Subgraph_BuyExit.DrawStyle = DRAWSTYLE_ARROW_DOWN;
    Subgraph_BuyExit.PrimaryColor = RGB(255, 128, 128);
    Subgraph_BuyExit.LineWidth = 2;
    Subgraph_BuyExit.DrawZeros = false;

    Subgraph_SellEntry.Name = "Sell Entry";
    Subgraph_SellEntry.DrawStyle = DRAWSTYLE_ARROW_DOWN;
    Subgraph_SellEntry.PrimaryColor = RGB(255, 0, 0);
    Subgraph_SellEntry.LineWidth = 2;
    Subgraph_SellEntry.DrawZeros = false;

    Subgraph_SellExit.Name = "Sell Exit";
    Subgraph_SellExit.DrawStyle = DRAWSTYLE_ARROW_UP;
    Subgraph_SellExit.PrimaryColor = RGB(128, 255, 128);
    Subgraph_SellExit.LineWidth = 2;
    Subgraph_SellExit.DrawZeros = false;

    Input_Enabled.Name = "Enabled";
    Input_Enabled.SetYesNo(0);
    Input_Enabled.SetDescription("This input enables the study and allows it to function. Otherwise, it does nothing.");

    Input_ReferenceChartForPrice.Name = "Reference Chart For Price";
    Input_ReferenceChartForPrice.SetChartNumber(0);

    // This is false by default. Orders will be simulated.
    sc.SendOrdersToTradeService = false;

    // These variables are not used when trading another Symbol and/or Trade Account compared to what the chart is set to.
    sc.AllowMultipleEntriesInSameDirection = true;
    sc.MaximumPositionAllowed = 20000;
    sc.SupportReversals = true;
    sc.AllowOppositeEntryWithOpposingPositionOrOrders = true;
    sc.SupportAttachedOrdersForTrading = false;
    sc.UseGUIAttachedOrderSetting = false;
    sc.CancelAllOrdersOnEntriesAndReversals= true;
    sc.AllowEntryWithWorkingOrders = true;
    sc.CancelAllWorkingOrdersOnExit = true;

    //
    sc.AllowOnlyOneTradePerBar = false;

    //This needs to be set to true when a trading study uses trading functions.
    sc.MaintainTradeStatisticsAndTradesData = true;

    sc.ReceiveNotificationsForChangesToOrdersPositionsForAnySymbol = true;

    sc.AutoLoop = true;
    sc.GraphRegion = 0;

    return;
  }

  //These must be outside of the sc.SetDefaults code block since they have a dependency upon an actual chart object existing. They are not used in this example.
  sc.SupportTradingScaleIn = 0;
  sc.SupportTradingScaleOut = 0;


  int& r_BarIndexOfOrder = sc.GetPersistentInt(1);
  int& r_InternalOrderID = sc.GetPersistentInt(2);
  int& r_PerformedOrderModification = sc.GetPersistentInt(3);

  if (!Input_Enabled.GetYesNo())
  {
    r_BarIndexOfOrder = 0;
    r_InternalOrderID = 0;
    r_PerformedOrderModification = 0;

    return;
  }

  if (sc.LastCallToFunction)
    return;//nothing to do

  if (sc.ChartIsDownloadingHistoricalData(Input_ReferenceChartForPrice.GetChartNumber())
    || sc.IsFullRecalculation
    || sc.ServerConnectionState != SCS_CONNECTED
    )
  {
    return;
  }

  // Run the below code only on the last bar
  if (sc.Index < sc.ArraySize - 1)
    return;

  SCFloatArray LastPriceArrayFromChartToTrade;
  sc.GetChartArray
    ( Input_ReferenceChartForPrice.GetChartNumber()
    , SC_LAST
    , LastPriceArrayFromChartToTrade
    );

  if (LastPriceArrayFromChartToTrade.GetArraySize() == 0)
    return;

  int LastIndexOfArrayFromChartToTrade = LastPriceArrayFromChartToTrade.GetArraySize() - 1;

  const char* SymbolToTrade = "XAUUSD";
  const char* TradeAccount = "Sim3";

  const int OrderQuantity = 100;

  s_SCPositionData PositionData;
  sc.GetTradePositionForSymbolAndAccount(PositionData, SymbolToTrade, sc.SelectedTradeAccount);
  if (PositionData.PositionQuantity == 0 && PositionData.WorkingOrdersExist == 0 && r_InternalOrderID == 0)
  {
    // Create an s_SCNewOrder object.
    s_SCNewOrder NewOrder;
    NewOrder.OrderQuantity = OrderQuantity;
    NewOrder.OrderType = SCT_ORDERTYPE_LIMIT;
    NewOrder.TimeInForce = SCT_TIF_DAY;
    NewOrder.Price1
      = LastPriceArrayFromChartToTrade[LastIndexOfArrayFromChartToTrade] - 10 * sc.TickSize;
    
    //Specify a Target and a Stop with 8 tick offsets. Only 1 Target and 1 Stop can be supported when trading a Symbol and Trade Account different than the chart the trading system study is applied to.
    NewOrder.Target1Offset = 8*sc.TickSize;
    NewOrder.Stop1Offset = 8*sc.TickSize;

    // If this is left at the default of 0, then it will be automatically set.
    NewOrder.OCOGroup1Quantity = OrderQuantity;

    NewOrder.Symbol = SymbolToTrade;
    NewOrder.TradeAccount = TradeAccount; //sc.SelectedTradeAccount;

    int Result = static_cast<int>(sc.BuyOrder(NewOrder));
    
    if (Result > 0)
    {
      r_BarIndexOfOrder = sc.Index;
      r_InternalOrderID = NewOrder.InternalOrderID;
    }

  }
  else if (r_InternalOrderID != 0)
  {
    s_SCTradeOrder ExistingOrderDetails;
    if (sc.GetOrderByOrderID(r_InternalOrderID, ExistingOrderDetails))
    {
      //If original submitted order is still working.
      if (IsWorkingOrderStatus(ExistingOrderDetails.OrderStatusCode) )
      {
        //When 1 new bar is added to chart since the original order submission
        if (r_PerformedOrderModification == 0 && sc.Index >= r_BarIndexOfOrder + 1)
        {
          //Modify the order
          s_SCNewOrder ModifyOrder;
          ModifyOrder.InternalOrderID = r_InternalOrderID;
          ModifyOrder.Price1 = LastPriceArrayFromChartToTrade[LastIndexOfArrayFromChartToTrade] - 12 * sc.TickSize;

          if (sc.ModifyOrder(ModifyOrder) > 0)
            r_PerformedOrderModification = 1;
        }
        // When 2 new bars added to chart since the original order submission
        else if (sc.Index >= r_BarIndexOfOrder + 2)
        {
          //Cancel the order
          sc.CancelOrder(r_InternalOrderID);
        }
      }
    }
  }
}

Date Time Of Last Edit: 2023-06-29 18:28:32