Support Board
Date/Time: Sun, 02 Feb 2025 16:55:19 +0000
Post From: ACSIL - trailing stop loss and orders
[2019-09-16 22:48:44] |
MattK - Posts: 42 |
Hi guys! I'm working on an automated trading system. Simply put: trying to buy one tick above the previous candle and trail the stop loss one tick under the previous low. However, it is not behaving as I would like. I'm trying to debug and put messages in the activity log but can't figure out what is wrong with my orders and stop loss. If you could help me I would love it. When I backtest the system, I end up with trades where the loss is $400 or $5k, etc even though I put a stop loss at 6 ticks under the price. Thanks in advance. Matt -- UPDATED CODE -- // 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("Reversal strategy") //This is the basic framework of a study function. Change the name 'TemplateFunction' to what you require. SCSFExport scsf_ReversalStrategy(SCStudyInterfaceRef sc) { //Define references to the Subgraphs and Inputs for easy reference SCSubgraphRef BuyEntrySubgraph = sc.Subgraph[0]; SCSubgraphRef BuyExitSubgraph = sc.Subgraph[1]; SCSubgraphRef ATRSubgraph = sc.Subgraph[2]; SCSubgraphRef EMASubgraph = sc.Subgraph[3]; SCString DebugMessage; // Section 1 - Set the configuration variables and defaults if (sc.SetDefaults) { sc.GraphName = "Reversal long strategy"; sc.AutoLoop = 1; //Automatic looping is enabled. BuyEntrySubgraph.Name = "Buy Entry"; BuyEntrySubgraph.DrawStyle = DRAWSTYLE_ARROW_UP; BuyEntrySubgraph.PrimaryColor = RGB(0, 255, 0); BuyEntrySubgraph.LineWidth = 2; BuyEntrySubgraph.DrawZeros = false; BuyExitSubgraph.Name = "Buy Exit"; BuyExitSubgraph.DrawStyle = DRAWSTYLE_ARROW_DOWN; BuyExitSubgraph.PrimaryColor = RGB(255, 128, 128); BuyExitSubgraph.LineWidth = 2; BuyExitSubgraph.DrawZeros = false; sc.Input[0].Name = "Float Input"; sc.Input[0].SetFloat(0.0f); return; } // Section 2 - Do data processing here float currentPrice = sc.BaseData[SC_LAST][sc.Index]; float currentHigh = sc.BaseData[SC_HIGH][sc.Index]; float previousHigh = sc.BaseData[SC_HIGH][sc.Index-1]; float previous2High = sc.BaseData[SC_HIGH][sc.Index-2]; float currentLow = sc.BaseData[SC_LOW][sc.Index]; float previousLow = sc.BaseData[SC_LOW][sc.Index-1]; float previous2Low = sc.BaseData[SC_LOW][sc.Index-2]; float previousClose = sc.BaseData[SC_CLOSE][sc.Index-1]; float previous2Close = sc.BaseData[SC_CLOSE][sc.Index-2]; float previousHighCloseDiff = sc.BaseData[SC_HIGH][sc.Index-1] - sc.BaseData[SC_CLOSE][sc.Index-1]; // Calculate the Average True Range sc.ATR(sc.BaseDataIn, ATRSubgraph, 10, MOVAVGTYPE_SIMPLE); float ATR = ATRSubgraph[sc.Index]; // Value of the current ATR // Calculate the EMA sc.ExponentialMovAvg(sc.BaseDataIn[SC_LAST], EMASubgraph, 100); float EMA = EMASubgraph[sc.Index]; // Value of the current EMA s_SCPositionData PositionData; sc.GetTradePosition(PositionData); // Use persistent variables to remember attached order IDs so they can be modified or canceled. int& OrderId = sc.GetPersistentInt(1); int& Stop1OrderID = sc.GetPersistentInt(2); float orderPrice = sc.GetPersistentFloat(1); float NewPossibleStop = sc.GetPersistentFloat(2); float orderStop = sc.GetPersistentFloat(3); float currentStop = sc.GetPersistentFloat(4); int Hour = sc.BaseDateTimeIn[sc.Index].GetHour(); int Minute = sc.BaseDateTimeIn[sc.Index].GetMinute(); // Data processing once the bar has closed. if(sc.GetBarHasClosedStatus()==BHCS_BAR_HAS_CLOSED) { // Cancel the pending order if (PositionData.PositionQuantity == 0 && OrderId != 0) { sc.FlattenAndCancelAllOrders(); OrderId = 0; Stop1OrderID = 0; } if (PositionData.PositionQuantity == 0 && ATR >= 1.8 && currentLow > EMA && currentLow <= previousLow) { // Mark the signal on the chart BuyEntrySubgraph[sc.Index] = sc.Low[sc.Index]; // Create a market order and enter long. s_SCNewOrder NewOrder; NewOrder.OrderQuantity = 1; NewOrder.OrderType = SCT_ORDERTYPE_STOP_LIMIT; NewOrder.TimeInForce = SCT_TIF_DAY; NewOrder.Price1 = currentHigh + 1*sc.TickSize; NewOrder.Price2 = currentHigh + 4*sc.TickSize; NewOrder.OCOGroup1Quantity = 1; NewOrder.Stop1Price = currentHigh - 3*sc.TickSize; // This is a common setting and applies to all Stop Attached Orders set on the main order. NewOrder.MoveToBreakEven.Type=MOVETO_BE_ACTION_TYPE_OFFSET_TRIGGERED; //After 5 ticks of profit, the stop order will be moved to breakeven NewOrder.MoveToBreakEven.TriggerOffsetInTicks= 4; NewOrder.MoveToBreakEven.BreakEvenLevelOffsetInTicks= 0; // Using this variable to log a message orderPrice = currentHigh + 1*sc.TickSize; DebugMessage.Format("Signal at: %f", orderPrice); sc.AddMessageToLog(DebugMessage, 1); sc.BuyEntry(NewOrder); // Remember the order ID for subsequent modification and cancellation Stop1OrderID = NewOrder.Stop1InternalOrderID; OrderId = NewOrder.InternalOrderID; orderStop = currentHigh - 3*sc.TickSize; } // Update the trailing stop loss if the new low is higher than the previous low. // Gotta make sure the new stop loss is not lower than the initial one NewPossibleStop = currentLow - 2*sc.TickSize; // COMPARE INITIAL STOP TO NEW STOP IS NOT WORKING RIGHT NOW if (PositionData.PositionQuantity == 1 && currentLow > previousLow && currentHigh > previousHigh && currentStop < NewPossibleStop && NewPossibleStop > orderStop) { s_SCTradeOrder ExistingOrder; if (sc.GetOrderByOrderID(Stop1OrderID, ExistingOrder) != SCTRADING_ORDER_ERROR) { s_SCNewOrder ModifyOrder; ModifyOrder.InternalOrderID = Stop1OrderID; ModifyOrder.Price1 = NewPossibleStop; sc.ModifyOrder(ModifyOrder); DebugMessage.Format("Current time: %d:%d", Hour, Minute); sc.AddMessageToLog(DebugMessage, 1); DebugMessage.Format("Updating stop loss to: %f on entry: %f", NewPossibleStop, orderPrice); sc.AddMessageToLog(DebugMessage, 1); DebugMessage.Format("Order price: %f", orderPrice); sc.AddMessageToLog(DebugMessage, 1); currentStop = currentLow - 2*sc.TickSize; } } // Flatten and cancel all if there is a current position but no stop if (PositionData.PositionQuantity == 1 && Stop1OrderID == 0) { sc.FlattenAndCancelAllOrders(); } // Flatten and cancel all orders if it is right before the session ending. if (Hour == 14 && Minute ==59) { sc.FlattenAndCancelAllOrders(); } } } Date Time Of Last Edit: 2019-09-17 17:46:57
|