// ============================================================================= // GaryStrat.cpp // // NOTE FOR SIERRA CHART SUPPORT REVIEW: // Proprietary signal/filter logic has been REMOVED and replaced with a // neutral placeholder. Everything related to ORDER MECHANICS is retained // exactly as it ran on 02-SEP-2026 during the resubmission-burst incident: // - single market entry per closed bar (edge-gated via persistent var) // - attached Stop/Target bracket (OCO) // - two-step arm/confirm test order feature // - optional bounded flatten window + mandatory 4:50-5:00 PM ET flatten // - position tracking and consecutive-loss halt // The entry signal itself is not relevant to this investigation: with the // placeholder signal disabled, this study submits nothing. During the // incident, ALL burst orders were tagged to a Trade Window .twconfig // (manual trade window), not to this study's submissions. // ============================================================================= #include "sierrachart.h" SCDLLName("Gary Strat") SCSFExport scsf_GaryStrat(SCStudyInterfaceRef sc) { // ---- Subgraphs ---- SCSubgraphRef Subgraph_HaltStatus = sc.Subgraph[7]; // ---- Inputs ---- SCInputRef Input_EnableTrading = sc.Input[0]; SCInputRef Input_MaxContracts = sc.Input[1]; SCInputRef Input_AllowLong = sc.Input[2]; SCInputRef Input_AllowShort = sc.Input[3]; SCInputRef Input_MaxConsecutiveLosses = sc.Input[4]; // Generic signal-configuration slots (logic removed for sharing) SCInputRef Input_SignalConfig1 = sc.Input[5]; SCInputRef Input_SignalConfig2 = sc.Input[6]; SCInputRef Input_SignalConfig3 = sc.Input[7]; SCInputRef Input_SignalConfig4 = sc.Input[8]; SCInputRef Input_SignalConfig5 = sc.Input[9]; SCInputRef Input_MinStopTicks = sc.Input[15]; SCInputRef Input_MaxStopTicks = sc.Input[16]; SCInputRef Input_TargetMultiplier = sc.Input[17]; SCInputRef Input_TargetTickAdjustment = sc.Input[18]; SCInputRef Input_UseTradingWindow = sc.Input[19]; SCInputRef Input_TradingStartTime = sc.Input[20]; SCInputRef Input_TradingEndTime = sc.Input[21]; SCInputRef Input_UseFlattenTime = sc.Input[22]; SCInputRef Input_FlattenTime = sc.Input[23]; SCInputRef Input_TestOrderArm = sc.Input[24]; SCInputRef Input_TestOrderConfirmFire = sc.Input[25]; SCInputRef Input_ResetHaltArm = sc.Input[26]; SCInputRef Input_ResetHaltConfirm = sc.Input[27]; SCInputRef Input_ExecuteDuringOpenWindow = sc.Input[28]; SCInputRef Input_ExecuteDuringCloseWindow = sc.Input[29]; SCInputRef Input_EnableMandatoryFlattenWindow = sc.Input[34]; if (sc.SetDefaults) { sc.GraphName = "Gary Strat"; sc.StudyDescription = "Custom trading strategy. Signal/filter logic proprietary and " "removed for this shared copy; order-submission, bracket, and " "flatten mechanics identical to production build."; sc.AutoLoop = 1; sc.GraphRegion = 0; sc.FreeDLL = 1; sc.AllowMultipleEntriesInSameDirection = 0; sc.SupportReversals = 0; sc.CancelAllOrdersOnEntriesAndReversals = 1; sc.AllowOppositeEntryWithOpposingPositionOrOrders = 0; sc.SupportAttachedOrdersForTrading = 1; sc.MaximumPositionAllowed = 1; // overwritten from input each call below sc.SendOrdersToTradeService = 1; // overwritten every call below Subgraph_HaltStatus.Name = "Halted For Day (1=Yes, 0=No)"; Subgraph_HaltStatus.DrawStyle = DRAWSTYLE_IGNORE; Input_EnableTrading.Name = "Enable Trading"; Input_EnableTrading.SetYesNo(1); Input_MaxContracts.Name = "Max Contracts (Position Size)"; Input_MaxContracts.SetInt(1); Input_MaxContracts.SetIntLimits(1, 10); Input_AllowLong.Name = "Allow Long Entries"; Input_AllowLong.SetYesNo(1); Input_AllowShort.Name = "Allow Short Entries"; Input_AllowShort.SetYesNo(1); Input_MaxConsecutiveLosses.Name = "Max Consecutive Losses Before Daily Halt"; Input_MaxConsecutiveLosses.SetInt(3); Input_MaxConsecutiveLosses.SetIntLimits(1, 20); // ---- Generic signal-configuration placeholders (logic removed) ---- Input_SignalConfig1.Name = "Signal Config 1"; Input_SignalConfig1.SetInt(10); Input_SignalConfig1.SetIntLimits(3, 100); Input_SignalConfig2.Name = "Signal Config 2"; Input_SignalConfig2.SetFloat(0.5f); Input_SignalConfig2.SetFloatLimits(0.0f, 1.0f); Input_SignalConfig3.Name = "Signal Config 3"; Input_SignalConfig3.SetFloat(0.25f); Input_SignalConfig3.SetFloatLimits(0.0f, 1.0f); Input_SignalConfig4.Name = "Signal Config 4"; Input_SignalConfig4.SetInt(20); Input_SignalConfig4.SetIntLimits(5, 200); Input_SignalConfig5.Name = "Signal Config 5 (ticks)"; Input_SignalConfig5.SetInt(4); Input_SignalConfig5.SetIntLimits(0, 100); Input_MinStopTicks.Name = "Minimum Stop (Ticks)"; Input_MinStopTicks.SetInt(6); Input_MinStopTicks.SetIntLimits(1, 500); Input_MaxStopTicks.Name = "Maximum Stop (Ticks)"; Input_MaxStopTicks.SetInt(60); Input_MaxStopTicks.SetIntLimits(1, 2000); Input_TargetMultiplier.Name = "Target Multiplier (x Stop)"; Input_TargetMultiplier.SetFloat(1.5f); Input_TargetMultiplier.SetFloatLimits(0.1f, 10.0f); Input_TargetTickAdjustment.Name = "Target Tick Adjustment (subtracted, ticks)"; Input_TargetTickAdjustment.SetInt(1); Input_TargetTickAdjustment.SetIntLimits(0, 50); Input_UseTradingWindow.Name = "Restrict Entries To Time Window"; Input_UseTradingWindow.SetYesNo(0); Input_TradingStartTime.Name = "Trading Window Start Time"; Input_TradingStartTime.SetTime(HMS_TIME(9, 30, 0)); Input_TradingEndTime.Name = "Trading Window End Time"; Input_TradingEndTime.SetTime(HMS_TIME(15, 45, 0)); Input_UseFlattenTime.Name = "Flatten Position At Time"; Input_UseFlattenTime.SetYesNo(0); Input_FlattenTime.Name = "Flatten Time"; Input_FlattenTime.SetTime(HMS_TIME(15, 55, 0)); Input_TestOrderArm.Name = "TEST STEP 1 of 2: Arm Test Order (set this first, by itself)"; Input_TestOrderArm.SetYesNo(0); Input_TestOrderConfirmFire.Name = "TEST STEP 2 of 2: Confirm Fire Test Order (only after Step 1 is Yes)"; Input_TestOrderConfirmFire.SetYesNo(0); Input_ResetHaltArm.Name = "RESET HALT STEP 1 of 2: Arm Reset (clears consecutive-loss halt)"; Input_ResetHaltArm.SetYesNo(0); Input_ResetHaltConfirm.Name = "RESET HALT STEP 2 of 2: Confirm Reset (only after Step 1 is Yes)"; Input_ResetHaltConfirm.SetYesNo(0); Input_ExecuteDuringOpenWindow.Name = "Execute Orders During 9:30-9:40 AM ET Window"; Input_ExecuteDuringOpenWindow.SetYesNo(0); Input_ExecuteDuringCloseWindow.Name = "Execute Orders During 3:50-4:00 PM ET Window"; Input_ExecuteDuringCloseWindow.SetYesNo(0); Input_EnableMandatoryFlattenWindow.Name = "Enable Mandatory 4:50-5:00 PM ET Flatten & No New Trades"; Input_EnableMandatoryFlattenWindow.SetYesNo(1); return; } // ------------------------------------------------------------------- // Persistent variables (retained across calls) // ------------------------------------------------------------------- int& r_LastProcessedClosedBar = sc.GetPersistentInt(1); int& r_PrevPositionQuantity = sc.GetPersistentInt(2); int& r_ConsecutiveLosses = sc.GetPersistentInt(3); int& r_TradingHaltedForDay = sc.GetPersistentInt(4); int& r_SessionInitialized = sc.GetPersistentInt(5); if (sc.IsFullRecalculation) return; // never submit orders during a full study recalculation // (rejected by Sierra Chart with error -8998) int& r_PrevTestOrderCombined = sc.GetPersistentInt(7); int& r_TestOrderArmedLogged = sc.GetPersistentInt(8); if (r_LastProcessedClosedBar == 0) { r_LastProcessedClosedBar = -1; // force first-run processing } sc.MaximumPositionAllowed = Input_MaxContracts.GetInt(); // Keep SendOrdersToTradeService in sync with whatever mode Sierra Chart // is actually in right now (SIM vs live). A mismatch here causes every // order to be silently rejected with a consistency error. sc.SendOrdersToTradeService = sc.GlobalTradeSimulationIsOn ? 0 : 1; // ------------------------------------------------------------------- // TEST ORDER FIRING WITH BRACKETS (two-step arm/confirm, no popup) // Runs FIRST, every call, before any warmup/gate. // // Step 1: "Arm Test Order" -> Yes. Logs a message; sends nothing. // Step 2: "Confirm Fire Test Order" -> Yes while Step 1 is Yes. // Fires one 1-lot SELL market order with Stop/Target bracket // attached. Fires exactly once per Arm+Confirm cycle. // ------------------------------------------------------------------- int TestOrderArmed = Input_TestOrderArm.GetYesNo(); int TestOrderConfirm = Input_TestOrderConfirmFire.GetYesNo(); int TestOrderCombined = (TestOrderArmed == 1 && TestOrderConfirm == 1) ? 1 : 0; if (TestOrderArmed == 1 && r_TestOrderArmedLogged == 0) { sc.AddMessageToLog( "Test Order: ARMED. Set Step 2 (Confirm Fire) to Yes to actually send the order.", 0); r_TestOrderArmedLogged = 1; } else if (TestOrderArmed == 0) { r_TestOrderArmedLogged = 0; } if (TestOrderCombined == 1 && r_PrevTestOrderCombined == 0) { int TestStopTicks = Input_MinStopTicks.GetInt(); int TestTargetTicks = (int)((TestStopTicks * Input_TargetMultiplier.GetFloat()) + 0.5f) - Input_TargetTickAdjustment.GetInt(); if (TestTargetTicks < 1) TestTargetTicks = 1; s_SCNewOrder TestOrder; TestOrder.OrderQuantity = 1; TestOrder.OrderType = SCT_ORDERTYPE_MARKET; TestOrder.Target1Offset = TestTargetTicks * sc.TickSize; TestOrder.AttachedOrderTarget1Type = SCT_ORDERTYPE_LIMIT; TestOrder.Stop1Offset = TestStopTicks * sc.TickSize; TestOrder.AttachedOrderStop1Type = SCT_ORDERTYPE_STOP; int SendResult = sc.SellEntry(TestOrder); SCString TestMsg; if (SendResult > 0) { TestMsg.Format( "TEST ORDER submitted OK (result code %d): 1-lot SELL market, " "Stop %d ticks, Target %d ticks.", SendResult, TestStopTicks, TestTargetTicks); } else { TestMsg.Format( "TEST ORDER FAILED to submit (result code %d). Check the Trade Service Log.", SendResult); } sc.AddMessageToLog(TestMsg, 1); } r_PrevTestOrderCombined = TestOrderCombined; // ------------------------------------------------------------------- // RESET CONSECUTIVE-LOSS HALT (same two-step arm/confirm pattern) // ------------------------------------------------------------------- int& r_PrevResetHaltCombined = sc.GetPersistentInt(9); int& r_ResetHaltArmedLogged = sc.GetPersistentInt(10); int ResetHaltArmed = Input_ResetHaltArm.GetYesNo(); int ResetHaltConfirm = Input_ResetHaltConfirm.GetYesNo(); int ResetHaltCombined = (ResetHaltArmed == 1 && ResetHaltConfirm == 1) ? 1 : 0; if (ResetHaltArmed == 1 && r_ResetHaltArmedLogged == 0) { sc.AddMessageToLog( "Reset Halt: ARMED. Set Step 2 (Confirm) to Yes to clear the halt and loss counter.", 0); r_ResetHaltArmedLogged = 1; } else if (ResetHaltArmed == 0) { r_ResetHaltArmedLogged = 0; } if (ResetHaltCombined == 1 && r_PrevResetHaltCombined == 0) { r_ConsecutiveLosses = 0; r_TradingHaltedForDay = 0; sc.AddMessageToLog("Trading halt manually RESET. Consecutive loss counter cleared.", 1); } r_PrevResetHaltCombined = ResetHaltCombined; int LastClosedBar = sc.Index - 1; int WarmupBars = Input_SignalConfig1.GetInt() + Input_SignalConfig4.GetInt() + 5; if (LastClosedBar < WarmupBars) return; // ------------------------------------------------------------------- // Position / trade-outcome tracking (runs every call, every tick) // ------------------------------------------------------------------- s_SCPositionData PositionData; sc.GetTradePosition(PositionData); if (r_PrevPositionQuantity != 0 && PositionData.PositionQuantity == 0) { if (PositionData.LastTradeProfitLoss > 0) r_ConsecutiveLosses = 0; else r_ConsecutiveLosses++; if (r_ConsecutiveLosses >= Input_MaxConsecutiveLosses.GetInt()) { r_TradingHaltedForDay = 1; SCString Msg; Msg.Format("[Gary Strat] HALTED for the day after %d consecutive losses.", r_ConsecutiveLosses); sc.AddMessageToLog(Msg, 1); } } r_PrevPositionQuantity = PositionData.PositionQuantity; Subgraph_HaltStatus[sc.Index] = (float)r_TradingHaltedForDay; // ------------------------------------------------------------------- // Optional flatten-at-time. BOUNDED to a 10-minute window starting at // the configured time, not an open-ended ">= FlattenTime" check. // ------------------------------------------------------------------- if (Input_UseFlattenTime.GetYesNo()) { double NowTimeOfDaySeconds = sc.BaseDateTimeIn[sc.Index].GetTimeInSeconds(); double FlattenStartSeconds = (double)Input_FlattenTime.GetTime(); double FlattenEndSeconds = FlattenStartSeconds + 600.0; // +10 minutes if (NowTimeOfDaySeconds >= FlattenStartSeconds && NowTimeOfDaySeconds < FlattenEndSeconds && PositionData.PositionQuantity != 0) { sc.FlattenAndCancelAllOrders(); } } // ------------------------------------------------------------------- // MANDATORY: never hold a position overnight. Flatten AND cancel all // attached bracket orders during the 4:50-5:00 PM ET window (bounded, // ahead of the CME 5:00-6:00 PM ET maintenance break). // ------------------------------------------------------------------- if (Input_EnableMandatoryFlattenWindow.GetYesNo()) { double NowTimeOfDaySeconds = sc.BaseDateTimeIn[sc.Index].GetTimeInSeconds(); double MandatoryFlattenStart = (double)HMS_TIME(16, 50, 0); double MandatoryFlattenEnd = (double)HMS_TIME(17, 0, 0); if (NowTimeOfDaySeconds >= MandatoryFlattenStart && NowTimeOfDaySeconds < MandatoryFlattenEnd && PositionData.PositionQuantity != 0) { sc.FlattenAndCancelAllOrders(); sc.AddMessageToLog( "MANDATORY 4:50 PM ET flatten: position closed and all bracket orders cancelled.", 1); } } // ------------------------------------------------------------------- // Only evaluate entry signals once per newly closed bar. // ------------------------------------------------------------------- if (r_LastProcessedClosedBar == LastClosedBar) return; r_LastProcessedClosedBar = LastClosedBar; // ========================================================= // PROPRIETARY SIGNAL LOGIC REMOVED FOR SHARING. // // This block originally computed the strategy's entry conditions from // multiple proprietary price-structure filters (Inputs 5-9, 28-33 and // associated persistent state). Output contract: at most one of // WantLong / WantShort is true on any given bar, evaluated once per // closed bar, never on intra-bar updates. No signal logic submits, // resubmits, modifies, or retries orders. // ========================================================= bool WantLong = false; bool WantShort = false; if (WantLong && WantShort) return; if (!WantLong && !WantShort) return; // ---- Stop / Target sizing ---- // Sizing inputs retained; the source measurement feeding the tick // calculation is proprietary and replaced here with the configured // minimum so the bracket mechanics remain inspectable. int StopTicks = Input_MinStopTicks.GetInt(); if (StopTicks < Input_MinStopTicks.GetInt()) StopTicks = Input_MinStopTicks.GetInt(); if (StopTicks > Input_MaxStopTicks.GetInt()) StopTicks = Input_MaxStopTicks.GetInt(); int TargetTicks = (int)((StopTicks * Input_TargetMultiplier.GetFloat()) + 0.5f) - Input_TargetTickAdjustment.GetInt(); if (TargetTicks < 1) TargetTicks = 1; // ---- Gate checks ---- if (!Input_EnableTrading.GetYesNo()) return; if (r_TradingHaltedForDay) return; if (PositionData.PositionQuantity != 0) return; if (Input_UseTradingWindow.GetYesNo()) { double NowTimeOfDaySeconds = (double)sc.BaseDateTimeIn[LastClosedBar].GetTimeInSeconds(); if (NowTimeOfDaySeconds < (double)Input_TradingStartTime.GetTime() || NowTimeOfDaySeconds > (double)Input_TradingEndTime.GetTime()) return; } s_SCNewOrder NewOrder; NewOrder.OrderQuantity = Input_MaxContracts.GetInt(); NewOrder.OrderType = SCT_ORDERTYPE_MARKET; NewOrder.Target1Offset = TargetTicks * sc.TickSize; NewOrder.AttachedOrderTarget1Type = SCT_ORDERTYPE_LIMIT; NewOrder.Stop1Offset = StopTicks * sc.TickSize; NewOrder.AttachedOrderStop1Type = SCT_ORDERTYPE_STOP; if (WantLong) sc.BuyEntry(NewOrder); else if (WantShort) sc.SellEntry(NewOrder); }