Login Page - Create Account

Support Board


Date/Time: Sat, 11 Jan 2025 09:58:06 +0000



Post From: 2 questions on programming a system

[2016-11-11 19:11:07]
User514837 - Posts: 47
Good afternoon, I am new to Sierra charts and have been learning it these days from its trial version. I wanted to try and see how good automated strategy development is and have been playing around with the ACSIL. Of course I went through many of the examples that come prepared in the ACS_Source folder, and I understood a bit how strategies are developed now. I tried to write my own MA crossover method and backtest it (I know there is one crossover method in the systems.cpp file, but I couldn't change the MA lengths, so I decided to write my own). It actually did work, meaning I was able to backtest the method, but it didn't work exactly as I had hoped. The system was entering the market immediately on an MA crossover, when I wanted this condition to be checked only on each bar close. By the way I applied this strategy at an intraday chart.

This is the code below:



// The top of every source code file must include this line
#include "sierrachart.h"

// For reference, refer to this page:
// Advanced Custom Study Interface and Language (ACSIL)

// This line is required. Change the text within the quote
// marks to what you want to name your group of custom studies.
SCDLLName("Custom Study DLL")

//This is the basic framework of a study function. Change the name 'TemplateFunction' to what you require.
SCSFExport scsf_TemplateFunction(SCStudyInterfaceRef sc)
{
  // Section 1 - Set the configuration variables and defaults
  SCSubgraphRef BuyEntrySubgraph = sc.Subgraph[0];
  SCSubgraphRef SellEntrySubgraph = sc.Subgraph[1];
  SCSubgraphRef FastSimpMovAvgSubgraph = sc.Subgraph[4];
  SCSubgraphRef SlowSimpMovAvgSubgraph = sc.Subgraph[5];

  SCInputRef Enabled = sc.Input[0];


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

    sc.GraphName = "Trading Example: Moving Average Crossover with Attached Orders";

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

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

    FastSimpMovAvgSubgraph.Name = "Fast Moving Average";
    FastSimpMovAvgSubgraph.DrawStyle = DRAWSTYLE_LINE;
    FastSimpMovAvgSubgraph.PrimaryColor = RGB(255, 255, 255);
    FastSimpMovAvgSubgraph.DrawZeros = false;
    FastSimpMovAvgSubgraph.LineWidth = 2;

    SlowSimpMovAvgSubgraph.Name = "Slow Moving Average";
    SlowSimpMovAvgSubgraph.DrawStyle = DRAWSTYLE_LINE;
    SlowSimpMovAvgSubgraph.PrimaryColor = RGB(0, 255, 0);
    SlowSimpMovAvgSubgraph.DrawZeros = false;
    SlowSimpMovAvgSubgraph.LineWidth = 2;

    Enabled.Name = "Enabled";
    Enabled.SetYesNo(0);


    sc.AllowMultipleEntriesInSameDirection = false;
    sc.MaximumPositionAllowed = 2;
    sc.SupportReversals = false;

    // This is false by default. Orders will go to the simulation system always.
    sc.SendOrdersToTradeService = false;

    sc.AllowOppositeEntryWithOpposingPositionOrOrders = false;

    // This can be false in this function because we specify Attached Orders directly with the order which causes this to be considered true when submitting an order.
    sc.SupportAttachedOrdersForTrading = false;

    sc.CancelAllOrdersOnEntriesAndReversals= false;
    sc.AllowEntryWithWorkingOrders = false;
    sc.CancelAllWorkingOrdersOnExit = true;

    // Only 1 trade for each Order Action type is allowed per bar.
    sc.AllowOnlyOneTradePerBar = true;

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

    sc.AutoLoop = 1;
    sc.GraphRegion = 0;

    // During development set this flag to 1, so the DLL can be modified. When development is completed, set it to 0 to improve performance.
    sc.FreeDLL = 0;

    return;
  }

  if (!Enabled.GetYesNo())
    return;
  

  // Use persistent variables to remember attached order IDs so they can be modified or canceled.
  int& Target1OrderID = sc.GetPersistentInt(1);
  int& Stop1OrderID = sc.GetPersistentInt(2);

  // Calculate the moving average
  sc.SimpleMovAvg(sc.Close, FastSimpMovAvgSubgraph, 20);
  sc.SimpleMovAvg(sc.Close, SlowSimpMovAvgSubgraph, 40);

  s_SCPositionData PositionData;
  sc.GetTradePosition(PositionData);
  if(PositionData.PositionQuantity != 0)
    return;

  // Create an s_SCNewOrder object.
  s_SCNewOrder NewOrder;
  NewOrder.OrderQuantity = 1;
  NewOrder.OrderType = SCT_ORDERTYPE_MARKET;
  NewOrder.TimeInForce = SCT_TIF_GOOD_TILL_CANCELED;

  //Specify a Target and a Stop with 8 tick offsets. We are specifying one Target and one Stop, additional targets and stops can be specified as well.
  NewOrder.Target1Offset = 8*sc.TickSize;
  NewOrder.Stop1Offset = 8*sc.TickSize;
  NewOrder.OCOGroup1Quantity = 1; // If this is left at the default of 0, then it will be automatically set.

  // Buy when the last price crosses the moving average from below.
  if (sc.CrossOver(FastSimpMovAvgSubgraph, SlowSimpMovAvgSubgraph) == CROSS_FROM_BOTTOM && sc.GetBarHasClosedStatus() == BHCS_BAR_HAS_CLOSED)
  {
    int Result = sc.BuyEntry(NewOrder);
    if (Result > 0) //If there has been a successful order entry, then draw an arrow at the low of the bar.
    {
      BuyEntrySubgraph[sc.Index] = sc.Low[sc.Index];

      // Remember the order IDs for subsequent modification and cancellation
      Target1OrderID = NewOrder.Target1InternalOrderID;
      Stop1OrderID = NewOrder.Stop1InternalOrderID;
    }
  }
  
  else if (sc.CrossOver(FastSimpMovAvgSubgraph, SlowSimpMovAvgSubgraph) == CROSS_FROM_TOP && sc.GetBarHasClosedStatus() == BHCS_BAR_HAS_CLOSED)
  {
    int Result = sc.SellEntry(NewOrder);
    if (Result > 0) //If there has been a successful order entry, then draw an arrow at the high of the bar.
    {
      SellEntrySubgraph[sc.Index] = sc.High[sc.Index];

      // Remember the order IDs for subsequent modification and cancellation
      Target1OrderID = NewOrder.Target1InternalOrderID;
      Stop1OrderID = NewOrder.Stop1InternalOrderID;
    }
  }
  
  
  // Section 2 - Do data processing here
  
  
}


A lot of this code is copy pasted from the example system . My question is: How can I make it only check the crossover condition on each bar close? Also, how can I set the system to close on opposite signal (if you are long, and you get a short signal, close the long position)?