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)? |