SRS: UC_6.1.2 — Margin Enforcement
| BA in Charge | Date Created | Version | Document References |
|---|---|---|---|
| Trang Nguyen | 2026-09-06 | v1 | RFQ_ Stack Trading Prop Tech V7.pdf; CR-20260827-001; CR-20260906-001; QnA_init_docs.md A-20 → A-27 |
UC_6.1.2 — Margin Enforcement
1. Overview
| Field | Content |
|---|---|
| ID | UC_6.1.2 |
| Use Case | Margin Enforcement (Universal Drawdown Safety Gate, Pre-Close Lockout, Forex Required Margin/notional compliance, Halt/Session Open handling — Required Margin canonical definition merged in per A-24, no separate UC_6.3, now split: Futures calculation moved to UC_6.1.3's Check 2, Forex calculation stays here) |
| Description | At each milestone signaled byUC_6.1.1's per-asset-class timeline thread (Futures) or the daily institutional rollover window (Forex), this UC executes the actual overnight risk enforcement action. At T-60min/T-30min/T-10min, the middleware broadcasts informational market-status warnings (Discord/Slack/Notification Center) with no enforcement action — Futures offsets from Official_Close_UTC, Forex offsets from Rollover_UTC (see §5 Basic Flow step 1). At T-3min, the middleware's own Layer 1 only updates the Lockout_Active state and broadcasts the notification; the actual Pre-Close Lockout order-filtering (locking new/increasing orders while still permitting closing/reducing orders) is enforced one layer lower, natively per platform — BR_6.1.2.1). At T-2min, the Risk Engine runs the Universal Drawdown Safety Gate — a 70%-of-stop-loss overnight equity check independent of margin math. ⚠️ Futures vs. Forex diverge once this gate passes: for Futures, this UC no longer computes the Required Margin audit itself — it dispatches unconditionally to UC_6.1.3, which now owns both the CME Overnight Margin pass/fail evaluation ("Check 2") and any resulting trim, sequenced after its own ES-Equivalent cap check ("Check 1") — see BR_6.1.2.4 and UC_6.1.3's Check 2. For Forex, this UC still runs its own 25% notional exposure cap check against MT5/TraderEvolution and only dispatches to UC_6.1.3 with a pre-computed Target_Limit when that check fails — Forex dispatches unconditionally on both MT5 and TraderEvolution, no longer routed through native leverage reduction first (CHR-102). At Halt_Start_UTC/Halt_End_UTC, order routing freezes/unfreezes. At Session_Open_UTC, overnight margin weighting is dropped, lockout filters release, and the account returns to standard intraday execution. Every milestone additionally constructs a notification payload for Zapier Flow 24; once the T-2min cycle finishes, the system broadcasts Enforcement_Complete regardless of outcome, while a per-user execution alert (NOTIFICATION WebSocket + Overnight_Auto_Liquidation_Alert email) fires only for a trader actually flattened/trimmed this cycle — dashboard position/account metrics refresh automatically off the live close order itself, with no Zapier involvement (BR_6.1.2.9). All milestone offsets (T-60/30/10/3/2/30sec, Rollover_UTC) are per-broker configurable values, not hardcoded (BR_6.1.2.8). |
| Zapier Flow | Flow 24 — Overnight Margin & Swap Monitor*(payload construction only — the broadcast/routing mechanism itself isUC_4.1.3's BR_4.1.3.2)* |
| Zapier Table | Table A (Forex level config —Max_Forex_Notional, absolute stop-loss threshold) · Table B (Futures level config — Max_Contracts, absolute stop-loss threshold) · Table C (shared cap-percent config — one variable per A-26, used by Forex Exposure Constraint here, and by Futures Margin Enforcement + News Events elsewhere) |
| 3rd Party | Rithmic gateway (Futures order routing + market close dispatch) · MT5 Gateway API (Forex order routing + market close dispatch, direct —CHR-102) · TraderEvolution Admin API (Forex order routing + market close dispatch, direct — CHR-102) |
No wireframe — backend enforcement engine with no UI screen of its own. Its notification payloads feed the Market Status Widget (UC_4.1.3) and the Discord/Slack/Dashboard broadcast channels via Flow 24.
⚠️ Applies to both SIM and LIVE account types — this UC's overnight margin/exposure enforcement (Universal Drawdown Safety Gate, Pre-Close Lockout, Futures/Forex Required Margin compliance, Halt/Session Open handling) runs identically for SIM and LIVE accounts, with no environment branching in the logic itself. See BR_6.1.2.11.
2. Trigger
Event-driven — each of the milestones this UC owns (T-60min, T-30min, T-10min, T-3min, T-2min, Halt Start, Halt End, Session Open) is signaled as the per-asset-class clock reaches that timestamp. This UC is purely reactive to those signals. (T-30sec is signaled directly to UC_6.1.3, not to this UC — per CR-20260906-001, this UC no longer owns any T-30sec action.)
3. Pre-conditions
| ID | Condition |
|---|---|
| P-1 | UC_6.1.1 has already derived a valid timeline thread for the asset class in question (its own P-3/P-4) — this UC has nothing to react to otherwise. |
| P-2 | CME_Instrument_Details holds the current-day CME overnight margin rate for Futures symbols, committed by UC_6.1.1 Step B — required input to UC_6.1.3's Check 2 (CME Overnight Margin Check), which now owns this calculation — see BR_6.1.2.4. |
| P-3 | The account'sAccount_Starting_Equity (fixed at challenge/level start — BR_6.1.2.2, A-25) and current Current_Account_Equity are both readable at T-2min. |
| P-4 | The Table C cap-percent config value (25%, shared across Futures margin, Forex exposure, and News Events — A-26) is readable at enforcement time. |
| P-5 | For Rithmic (Futures) only: the daily Rithmic No Trading From/To sync cron (BR_6.1.2.13) has already run and pushed that day's close/open timestamps for all ~31 whitelisted symbols to Rithmic — Layer 2's No Trading From/To window at T-3min depends on this; it is a separate cronjob from UC_6.1.1's own 01:00 UTC CME-ingestion cron. Does not apply to TraderEvolution or MT5 (Forex). |
4. Post-conditions
T-60min / T-30min / T-10min (Market status warnings)
- A
Warning_60/Warning_30/Warning_10payload is broadcast to traders via Discord, Slack, and the Notification Center. No order-filter, margin, or exposure state changes.
T-3min (Pre-Close Lockout)
- The API gateway rejects any new-position or exposure-increasing order for the closing asset class's symbols; closing/reducing orders continue to be accepted.
T-2min — Universal Drawdown Safety Gate breached
- Global
FLATTEN_ALLdispatched to the broker execution server for that user: all working orders cancelled, all open exposure cleared.
T-2min — Drawdown Gate passed (Futures or Forex)
- Futures: dispatched unconditionally to UC_6.1.3 — no shortfall pre-check and no pre-computed
Target_Limitfor the margin leg. UC_6.1.3 itself runs Check 1 (25% ES-Equivalent contract cap) then Check 2 (CME Overnight Margin vs.Available_Equity, the formerMAX(CME Overnight Margin, 25% notional)math) and determines whether/what to trim. See BR_6.1.2.4. - Forex (MT5 or TraderEvolution): still computed by this UC. If the 25% notional exposure sweep finds a shortfall, dispatched to UC_6.1.3 as a
TRIM_TO_COMPLIANCEcall withTarget_Limit = Allowed_Notional— unconditionally, for both platforms alike. No native leverage-reduction/Stop-Out path is checked or relied upon first (CHR-102).
T-2min — all checks pass
- No action; the position(s) roll into the overnight session unmodified. No per-user execution notification/email is generated for this user — see "T-2min cycle complete" below.
T-2min — a liquidation or trim was actually executed on a specific trader's account (Drawdown Gate FLATTEN_ALL, or a Required Margin/notional shortfall dispatched to and executed by UC_6.1.3)
- The dashboard's
POSITION_METRICS/ACCOUNT_METRICSWebSocket streams automatically detect and reflect the resulting flat/reduced position — this UC/the margin script does not publish or push these metrics itself; it relies entirely on the standard metrics pipeline already triggered by the live market order hitting the gateway. No Zapier involvement in this part. See BR_6.1.2.9. - The margin script fires a
NOTIFICATIONWebSocket event, surfacing an explanatory entry in that trader's Notification Center describing the liquidation/trim that was executed. - The margin script triggers the Zapier webhook for the post-execution
Overnight_Auto_Liquidation_Alertemail (SES-19) via AWS SES, sent to that specific trader only. - See BR_6.1.2.9 for full detail.
T-2min cycle complete (every cycle, regardless of whether any user was actually acted on)
- The system broadcasts
Enforcement_Completeonce the entire T-2min cycle finishes evaluating all accounts. This is a flow-level broadcast — it fires every cycle, independent of whether any individual trader was flattened/trimmed this time. See BR_6.1.2.9.
Halt Start / Halt End (Futures only — see §5 Basic Flow steps 8-9)
- Order routing locked/unlocked for the symbol;
Alert_Level = 'Halt_Active'/'Halt_Cleared'payload dispatched.
Session Open
- Overnight margin weighting dropped, normal FCM intraday margins restored; Pre-Close Lockout filters released;
Alert_Level = 'Session_Open'payload dispatched withAsset_Classand affected symbols.
5. Basic Flow
This flow follows RFQ V7's own point-by-point order ("Universal Drawdown Safety Gate" → "Asset-Specific Pre-Close Lockout" → "Futures Asset-Specific Margin Enforcement" → "Forex Specific Enforcement" → "Intraday Halt and New Session Open" → "Notification Routing Logic", lines 1689-1870), reordered slightly so the T-60/30/10 warnings and the T-3min lockout (which happen chronologically first) are presented before the T-2min checks.
-
T-60min / T-30min / T-10min — Market status warnings, no enforcement action. At each of these three timestamps, the middleware broadcasts a market-status warning to traders via Discord, Slack, and the Notification Center. The timestamp each milestone resolves to is asset-class-dependent, following the same per-asset-class timeline-thread model UC_6.1.1 already uses for T-3min/T-2min/T-30sec:
- Futures: anchored to the same daily cron-derived timeline thread UC_6.1.1 computes once per day from
Official_Close_UTC(committed by that UC's 01:00 UTC cron, BR_6.1.1.9). T-60min/T-30min/T-10min for Futures areOfficial_Close_UTC − 60min/− 30min/− 10minrespectively — the same reference timestamp, and the same per-asset-class thread, that T-3min/T-2min/T-30sec already derive from. No separate timing source for Futures. - Forex (MT5 and TraderEvolution): anchored instead to the daily institutional rollover window (
reset_time— the same rollover boundary BR_6.1.2.5's Forex notional sweep runs up to; value Ref:common_rules.md§22.1), since Forex has no CME-publishedOfficial_Close_UTCto derive from. T-60min/T-30min/T-10min for Forex areRollover_UTC − 60min/− 30min/− 10min, whereRollover_UTCis the fixed daily institutional rollover timestamp already resolved to the correct UTC instant for that day, DST included — this UC consumesRollover_UTCas a pre-resolved value; it does not run its own EST⇄EDT offset math (DST mechanism Ref: UC_4.1.3 BR_4.1.3.5). This is a separate timing source from Futures — Forex's warning milestones do not and cannot readCME_Instrument_Details. Warning_60/Warning_30/Warning_10— the three distinctAlert_Levelpayload values dispatched at each asset class's own T-60min, T-30min, and T-10min respectively (see step 12 below for the shared payload-construction mechanism). The payload itself is identical in shape across Futures and Forex; only the underlying timestamp source differs.- All of T-60min/T-30min/T-10min (and every other milestone offset in this UC) are per-broker configuration values, not hardcoded — see BR_6.1.2.8.
- Futures: anchored to the same daily cron-derived timeline thread UC_6.1.1 computes once per day from
-
T-3min — Asset-Specific Pre-Close Lockout activates. At exactly
Official_Close_UTC − 3minfor the asset class (Forex:Rollover_UTC − 3min, per step 1 above — this 3-minute offset is itself a per-broker config value, see BR_6.1.2.8), two layers of enforcement apply, and which actor performs which layer must not be confused:- 🔧 Layer 1 — performed by the middleware itself (Node.js/API gateway, platform-agnostic): the API gateway updates the
Lockout_Activestate (Pre_Close_Lockout) for that asset class's symbols, then broadcasts the milestone notification — the same Discord/Slack/Notification Center + market-status broadcast pattern already used for T-60min/T-30min/T-10min, just with its own distinct payload:- State update:
Lockout_Activeis set for the closing asset class's symbols. - Notification:
Widget_State = 'Lockout',Widget_Short_Text = 'Locked',Severity = 'CRITICAL', Copy: "Pre-Close Lockout", broadcast via Discord/Slack/Notification Center and the Market Status Widget.
- State update:
- 🏦 Layer 2 — performed by a native mechanism set up and executed at each platform/exchange itself (NOT the middleware): each broker/platform separately exposes its own native config that achieves the reduce-only effect at the exchange/server level, configured once ahead of time directly on that platform (not dispatched per-cycle by this UC's middleware). This is where the actual Order Filter Rule (reject any inbound order that would open a new position or increase net directional exposure within the closing asset class) and Authorized transactions (continue to permit closing/reducing transactions — partial fills, contract-size reductions, or fully flattening a position) are enforced:
- TraderEvolution (Forex): the instrument-level "Liquidation Only" trading status, applied via a TE Scheduler task calling the TraderEvolution Admin API — blocks new/increasing orders at the TE server itself, still permits reduce-only/flatten.
- MT5 (Forex): Close Only Trading Mode (
IMTConSymbol/IMTConGroupSymbol::TradeMode = TRADE_CLOSEONLY) — the MT5 server rejects new/increasing orders with error codeMT_RET_REQUEST_CLOSE_ONLY, still permits close/reduce orders. - Rithmic (Futures): the No Trading From / No Trading To window — a Rithmic-native configuration that permits only trades which move the account toward flat during the configured period; all other order types are rejected by the Rithmic gateway itself. ⚠️ Rithmic only — daily sync cronjob required (BR_6.1.2.13): unlike TraderEvolution/MT5 (configured once ahead of time, Ref: the Layer 2 intro above), Rithmic's No Trading From/To window must be re-pushed to the exchange side every day, because each symbol's close/open boundary shifts daily. A separate middleware cronjob — distinct from UC_6.1.1's own 01:00 UTC CME-ingestion cron — pushes that day's
Official_Close_UTC/Session_Open_UTCfor all ~31 whitelisted symbols to Rithmic, so the Adapter can set each symbol's No Trading From/To window for that day's T-3min boundary.
- The T-3min offset, and each broker-native mechanism's own window/schedule config above, are per-broker configurable variables — see BR_6.1.2.8.
- ⚠️ Trade Evolution sandbox testing note (Layer 2 only): when testing platform-native Layer 2 mechanisms above in the sandbox, only one currency pair is available for Forex — USD-TRY.
- 🔧 Layer 1 — performed by the middleware itself (Node.js/API gateway, platform-agnostic): the API gateway updates the
-
T-2min — Universal Drawdown Safety Gate runs first, ahead of any margin/volumetric calculation. Before any margin/exposure volumetric calculation runs, the Risk Engine computes:
Total_Equity_Loss = Account_Starting_Equity - Current_Account_EquityAccount_Starting_Equity— the account's balance fixed at the start of the current challenge/level.Current_Account_Equity— the account's real-time equity value at the moment of this T-2min check.Total_Equity_Loss— the resulting dollar loss since the challenge/level began; this is the value tested against the 70% threshold below.
IF Total_Equity_Loss ≥ 70% × Stop_Loss_Threshold (Table A/B) => FLATTEN_ALL IF Total_Equity_Loss < 70% × Stop_Loss_Threshold (Table A/B) => redirect to step 5 (Futures) and step 6 (Forex)Stop_Loss_Threshold— the level's absolute stop-loss dollar figure, configured in Table A for Forex / Table B for Futures. This value is not a flow-time lookup against a single global constant — it is the specific dollar figure already configured per account, assigned at the moment that account was created, whether through a successful promotion (challenge/level-up) or through a successful checkout flow (new purchase). The account carries its ownStop_Loss_Thresholdfrom that point forward; this step reads the value already attached to the account, it does not derive or recompute it at T-2min.70% × Stop_Loss_Threshold— the dollar boundary this gate tests against; reaching or crossing it revokes overnight holding privileges entirely, independently of whether margin/notional math would otherwise have passed.- Worked example — Futures account (gate passes):
Account_Starting_Equity = $50,000,Current_Account_Equity = $47,000→Total_Equity_Loss = $50,000 − $47,000 = $3,000. Table BStop_Loss_Threshold = $5,000→70% × $5,000 = $3,500. Since$3,000 < $3,500, the gate passes — this account's Futures positions redirect to step 5 for the Required Margin audit. - Worked example — Forex account (gate breached):
Account_Starting_Equity = $100,000,Current_Account_Equity = $92,500→Total_Equity_Loss = $100,000 − $92,500 = $7,500. Table AStop_Loss_Threshold = $10,000→70% × $10,000 = $7,000. Since$7,500 ≥ $7,000, the gate breaches — this account proceeds to step 4's globalFLATTEN_ALLinstead of step 7's Forex notional sweep.
-
T-2min — Gate breached → global FLATTEN_ALL, stop here. If the 70% boundary is breached, overnight holding privileges are revoked entirely: the system dispatches a global
FLATTEN_ALLto the broker execution server, cancelling all working orders and clearing all open exposure for that user. Since this is a liquidation actually executed against this specific account, it triggers the per-user execution-alert mechanism — see step 12a below (NOTIFICATIONWebSocket +Overnight_Auto_Liquidation_Alertemail).- ⚠️ Race condition — when this gate and a real-time breach coincide for the same account at effectively the same instant, a priority order governs which action actually applies. See BR_6.1.2.3.
-
T-2min — Gate passed → dispatch to UC_6.1.3 for Futures, unconditionally. ** For each closing Futures asset class, once the Drawdown Gate (step 3-4) passes, this UC calls UC_6.1.3 — TRIM_TO_COMPLIANCE unconditionally — not only when a shortfall is found. UC_6.1.3 itself runs its two-check sequence for the closing-now asset class:
- Check 1 — 25% ES-Equivalent Contract Cap (unchanged from CHR-100, already documented in UC_6.1.3): compares
Total_Portfolio_ES_EquivagainstFloor(Max_Contracts_ES_Equiv × Cap_Percent). - Check 2 — CME Overnight Margin Check (the calculation this step used to run inline here): once Check 1 is compliant, UC_6.1.3 computes
Required_Margin = SUM(Open_Contracts × CME_Overnight_Margin_Rate)for the remaining open positions in the closing asset class and compares it toAvailable_Equity(Total_Equity − Margin_Already_Encumbered_By_Other_Closed_Asset_Classes).
This UC's role for Futures is now limited to: running Gate 1 (steps 3-4) and triggering UC_6.1.3 once Gate 1 passes. This UC does not itself select which position to trim, compute
Required_Margin/Available_Equity, or dispatch close orders for Futures — that is entirely UC_6.1.3's responsibility (Check 1 + Check 2, CHR-100). Once UC_6.1.3's margin script actually executes a market close order against this account (whether a full trim-loop resolution or a T-30s Active FailsafeFLATTEN_ALL), the per-user execution-alert mechanism fires for that account — see step 12a below. See BR_6.1.2.4. - Check 1 — 25% ES-Equivalent Contract Cap (unchanged from CHR-100, already documented in UC_6.1.3): compares
-
T-2min through the institutional rollover (Ref:
common_rules.md§22.1) — Forex-Specific Enforcement. Independently of the Futures check (both run off the same Drawdown-Gate-passed branch), open Forex notional exposure is swept against a shared cap. Unlike the other milestones, this is not a single-instant check — it runs continuously from T-2min through the institutional rollover:IF Total_Open_Forex_Notional > Forex_Overnight_Cap_Percent × Total_Account_Equity => trigger TRIM_TO_COMPLIANCETotal_Open_Forex_Notional— the account's actual current open Forex notional exposure (all open Forex positions combined). Sourced differently per platform:-
🔧 TraderEvolution: this value can be read directly from TE's own API —
GET /accountDetailsreturns atotalPositionsValuefield, which isTotal_Open_Forex_Notionalfor that account. No middleware-side aggregation is required on TE; the platform already computes and exposes the total. -
🔧 MT5: MT5 does not expose an equivalent single ready-made field, so the Adapter (the MT5 API layer) — not the middleware itself — must calculate it directly by summing each open position's own
Position_Notional_Value, using these MT5 inputs:Input MQL5 property Python field Position size in lots POSITION_VOLUMEposition.volumeCurrent position price POSITION_PRICE_CURRENTposition.price_currentInstrument POSITION_SYMBOLposition.symbolContract size SYMBOL_TRADE_CONTRACT_SIZEsymbol.trade_contract_sizeInstrument calculation mode SYMBOL_TRADE_CALC_MODEsymbol.trade_calc_modeBase currency SYMBOL_CURRENCY_BASEsymbol.currency_baseProfit currency SYMBOL_CURRENCY_PROFITsymbol.currency_profitRetrieved via
positions_get()(open positions) andsymbol_info()(per-symbol contract/currency metadata). Each position's own notional value is calculated using the same 3-casePosition_Notional_Valueformula UC_6.1.3'sTRIM_TO_COMPLIANCEalgorithm uses (BR_6.1.3.3) — the same formula, not a separate one, so the notional figure this UC sweeps againstAllowed_Notionaland the notional figure UC_6.1.3 later trims against are computed identically:IF Quote_Currency == USD (e.g. EURUSD): Position_Notional_Value = Lot_Size × Contract_Size_Per_Lot × Current_Price IF Base_Currency == USD (e.g. USDJPY): Position_Notional_Value = Lot_Size × Contract_Size_Per_Lot IF neither leg is USD (cross pair, e.g. EURGBP): Position_Notional_Value = Lot_Size × Contract_Size_Per_Lot × FX_Conversion_Rate(Base_Currency → USD)Lot_Size— the position's size in lots (MT5POSITION_VOLUME/position.volume).Contract_Size_Per_Lot— the standard contract size for one lot (MT5SYMBOL_TRADE_CONTRACT_SIZE/symbol.trade_contract_size; typically 100,000 units of the base currency for a standard lot).Current_Price— the pair's current market price (MT5POSITION_PRICE_CURRENT/position.price_current), quote currency per 1 unit of base currency.FX_Conversion_Rate(Base_Currency → USD)— for a cross pair (neither leg is USD), the live conversion rate from the position's base currency directly to USD.- ⚠️ Live price requirement (same as UC_6.1.3):
Current_Priceand everyFX_Conversion_Ratemust be the real-time live market price from the MT5 Gateway API data stream at calculation time — never a cached, delayed, or stale rate. - Once each open Forex position's
Position_Notional_Valueis calculated this way, the Adapter sums them across all open Forex positions (converted to the account currency where needed, viaSYMBOL_CURRENCY_BASE/SYMBOL_CURRENCY_PROFIT) to arrive atTotal_Open_Forex_Notional— this aggregation happens inside the Adapter, not the middleware.
-
Forex_Overnight_Cap_Percent— the shared 25% cap-percent config value in Table C (A-26;Table_C_Cap_Percent). This is one config variable reused across three checks: this Forex exposure cap, the 25%-of-notional leg of the Futures Required Margin formula in step 5, and News Events'Notional_Cap_Percent— not three independently-set 25% constants.Total_Account_Equity— the account's current total equity (all asset classes combined).Forex_Overnight_Cap_Percent × Total_Account_Equity— the resulting dollar ceiling on total open Forex notional exposure the account may carry overnight (Allowed_Notional); this is whatTotal_Open_Forex_Notionalis tested against.- Worked example:
Total_Account_Equity = $100,000,Forex_Overnight_Cap_Percent = 25%(Table C) →Allowed_Notional = $100,000 × 0.25 = $25,000. The trader holds0.5 lots EURUSDatCurrent_Price = 1.10→Position_Notional_Value = 0.5 × 100,000 × 1.10 = $55,000(quote currency is USD, per the 3-case formula above) — this is alsoTotal_Open_Forex_Notional, since it's the only open Forex position.$55,000 > $25,000 (Allowed_Notional)→ the sweep fails: dispatch to UC_6.1.3 asTRIM_TO_COMPLIANCEwithTarget_Limit = $25,000— see step 8 below.
-
Forex shortfall — MT5 or TraderEvolution, unconditional dispatch. If
Total_Open_Forex_Notional > Allowed_Notional, the middleware dispatches to UC_6.1.3 as aTRIM_TO_COMPLIANCEcall withTarget_Limit = Allowed_Notional— for both platforms alike, with no native leverage-reduction/Stop-Out check first (CHR-102). There is no reliable guarantee that either MT5 or TraderEvolution natively enforces this exact 25% threshold, so the Node.js middleware itself calculates the overage and dispatches market close orders directly via the respective platform API (MT5 Gateway API or TraderEvolution Admin API) to scale the open notional back to the 25% limit — the same algorithmicTRIM_TO_COMPLIANCEloop used for Futures/Rithmic (T-120s Primary Loop), not a platform-native leverage-reduction/Stop-Out mechanism. No native-capability check is performed first on either platform. As with the Futures dispatch (step 6), the per-user execution-alert mechanism fires once UC_6.1.3's margin script actually executes a close order against this account — see step 12a below. -
Halt_Start_UTC — Maintenance Freeze. At the timestamp UC_6.1.1 signals for Halt Start, the gateway locks order routing for that symbol and dispatches
Alert_Level = 'Halt_Active'.- ⚠️ Futures-only milestone.
Halt_Start_UTCis sourced from theCME_Instrument_Detailstable (committed by UC_6.1.1 Step B) — a CME maintenance-window field that only exists for Futures instruments. Forex has no equivalent maintenance-halt window at present; MT5/TraderEvolution do not publish a comparable scheduled-halt timestamp this UC can read, so this step does not fire for Forex. It applies to Futures symbols only.
- ⚠️ Futures-only milestone.
-
Halt_End_UTC — Maintenance Unfreeze. Order routing unlocks; the system dispatches
Alert_Level = 'Halt_Cleared'.- ⚠️ Futures-only milestone — same reason as step 8 above:
Halt_End_UTCis also sourced fromCME_Instrument_Details, Futures-only data. This step does not fire for Forex.
- ⚠️ Futures-only milestone — same reason as step 8 above:
-
Session_Open_UTC — Day Margin Restoration and lockout release. At the timestamp UC_6.1.1 signals for Session Open:
- The system drops the overnight CME margin weighting and returns to normal FCM intraday day-trading margins.
- The API gateway releases the Pre-Close Lockout filters (step 2), returning the account to standard active execution.
- The middleware fires an outbound webhook with
Alert_Level = 'Session_Open', explicitly passing the affectedAsset_Classand symbols — this is the same signal UC_4.10.1/UC_4.15.1 Soft Lock unfreeze should key off dynamically (see UC_6.1.1 A-18 note — those two UCs currently document a fixed wall-clockreset_timeinstead; tracked as a separate Update Flow, not fixed by this UC).
-
Every milestone — notification payload. At each milestone (
Warning_60,Warning_30,Warning_10,Lockout_Active,Enforcement_Complete,Halt_Active,Halt_Cleared,Session_Open), the middleware publishes an outbound payload to the Flow 24 webhook catcher, mapping the specific symbol strings where applicable. This UC only constructs the payload — the 4-channel broadcast/routing logic itself is UC_4.1.3BR_4.1.3.2's Alert Level matrix, reused not rewritten here.Enforcement_Completespecifically is broadcast once the entire T-2min cycle finishes evaluating all accounts for this asset class — a flow-level signal, dispatched every cycle regardless of how many (if any) individual accounts were actually flattened/trimmed during it. See BR_6.1.2.9.12a. Per-user execution alert — only for a trader actually flattened/trimmed this cycle (client-confirmed, 2026-10-12). At T-2min, the Risk Engine's margin calculation runs silently for every account — no notification is generated purely from running the check. A notification is generated only when the system actively executes a liquidation (step 4's Drawdown Gate
FLATTEN_ALL) or a trim (steps 6/8's dispatch, once UC_6.1.3 actually fires a market close order) against that specific trader's account:- Dashboard metrics refresh — no Zapier involved. Because the margin script's close order is a real, live market order sent to the gateway, the account's
POSITION_METRICSandACCOUNT_METRICSWebSocket streams automatically detect the resulting flat/reduced position and refresh the UI through the existing metrics pipeline (UC_4.12.2 and sibling UCs) — this UC/the margin script does not publish these metrics itself, and this leg of the notification does not go through Zapier at all. NOTIFICATIONWebSocket — Notification Center entry. The margin script fires aNOTIFICATIONWebSocket event explaining the liquidation/trim in that trader's Notification Center (same delivery mechanism as UC_4.7.1BR_4.7.1.3's real-time push — no polling).Overnight_Auto_Liquidation_Alertemail (SES-19).** The margin script separately fires the post-executionOvernight_Auto_Liquidation_Alertemail via AWS SES to that specific trader, describing the automated action taken.
See BR_6.1.2.9 for full detail.
- Dashboard metrics refresh — no Zapier involved. Because the margin script's close order is a real, live market order sent to the gateway, the account's
6. Alternative Flows
-
Alt-1 — Drawdown Gate and Futures/Forex checks both pass; no enforcement action taken.
- Context: at T-2min,
Total_Equity_Lossis below the 70% threshold, and both the Futures Required Margin check and the Forex exposure check are within limits. - The position(s) roll into the overnight session unmodified. No
FLATTEN_ALL, no dispatch to UC_6.1.3, no leverage reduction. This is the expected common case, not an error path.
⚠️ Removed (CHR-102): the former "Alt-2 — Forex shortfall resolved via native leverage reduction, no trim dispatch" path no longer exists. Neither MT5's C++ Plugin nor TraderEvolution's native group leverage reduction is relied upon to clear a Forex overage — every Forex shortfall now dispatches unconditionally to UC_6.1.3 (see §5 step 7, BR_6.1.2.5).
- Context: at T-2min,
7. Exceptional Flows
-
Exc-1 — Universal Drawdown Safety Gate and a real-time Hard Breach (Level Stop) occur for the same account at effectively the same instant.
- Full priority-order rule: BR_6.1.2.3.
-
Exc-2 — Any failure in the margin/notional calculation itself at T-2min (missing CME overnight margin rate, a failed/unreachable notional lookup, a calculation exception, or any other error that prevents
Required_Margin/Available_Equity/Total_Open_Forex_Notionalfrom being computed with confidence) — universal fallback, not limited to the missing-CME-rate case.- ⚠️ Adam-confirmed universal fallback rule: "At any time if you encounter issues with margin calculation, all fallback plans are FLATTEN_ALL." This is a general standing rule, not scoped to any one failure mode — whatever specifically goes wrong inside the Required Margin (BR_6.1.2.4) or Forex notional-cap (BR_6.1.2.5) calculation, the system never proceeds on an uncertain/partial number, never silently lets an improperly-audited position roll overnight, and never substitutes a best-effort/default value in place of the missing input. The fallback is always the same: dispatch a global
FLATTEN_ALLfor the affected symbol/account and fire a Sev-1 alert to Slack#risk-ops. - The missing-CME-overnight-margin-rate case (
CME_Instrument_Detailshas no committed Step B value for the current trading day, soMAX(CME_Overnight_Margin_Rate × Contract_Count, ...)cannot be evaluated with a null rate) is the first concretely identified instance of this rule, and mirrors UC_6.1.3's own missing-risk-data failsafe — BR_6.1.3.2, "Missing risk data → failsafe, never a best-effort sort" (CHR-100) — but Adam's rule is the broader, standing principle this UC must apply to any margin-calculation failure mode it encounters, not only this one example. See BR_6.1.2.12 for the full rule statement.
- ⚠️ Adam-confirmed universal fallback rule: "At any time if you encounter issues with margin calculation, all fallback plans are FLATTEN_ALL." This is a general standing rule, not scoped to any one failure mode — whatever specifically goes wrong inside the Required Margin (BR_6.1.2.4) or Forex notional-cap (BR_6.1.2.5) calculation, the system never proceeds on an uncertain/partial number, never silently lets an improperly-audited position roll overnight, and never substitutes a best-effort/default value in place of the missing input. The fallback is always the same: dispatch a global
-
Exc-3 — A Forex
TRIM_TO_COMPLIANCEdispatch (MT5 or TraderEvolution) fails to resolve compliance in time (T-120s loop lags or fails).- Since CHR-102, this case is no longer conditioned on "no native leverage reduction available" — every Forex shortfall dispatches to UC_6.1.3 unconditionally, so this exception path applies universally. Ownership of the failure boundary passes to UC_6.1.3's own T-30s Node.js Active Failsafe (CR-20260906-001, universal per CHR-101) — this UC's responsibility ends at the dispatch call; it does not independently retry or escalate.
8. Business Rules
BR_6.1.2.1: Asset-Specific Pre-Close Lockout — Layer 1 state/notification only, Layer 2 owns the order filter rule
Full detail (Layer 1 state update/notification, Layer 2 per-platform native order-filter mechanisms, sandbox testing note) is specified in §5 Basic Flow step 2.
(Source: RFQ_ Stack Trading Prop Tech V7.pdf §Risk Enforcement Endpoints — "Asset-Specific Pre-Close Lockout Mechanism", lines 1716-1732)
BR_6.1.2.2: Universal Drawdown Safety Gate — 70% overnight equity check, runs before any margin math
Full formula and flatten/post-condition detail is specified in §5 Basic Flow steps 3-4. Account_Starting_Equity is not reset daily, and is distinct from the Daily Loss Limit's own Daily_Loss_Ratio-based formula (A-25).
BR_6.1.2.3: Priority order when the Drawdown Gate and a real-time breach coincide
When the Universal Drawdown Safety Gate (T-2min, overnight, scheduled) and a real-time Hard/Soft Breach (Daily Loss Limit / Max Drawdown, continuous) would both fire for the same account at effectively the same instant, the priority order is:
Hard Breach (Level Stop) > Universal Drawdown Safety Gate (70% overnight) > Daily Loss Limit soft breach
This extends BR_4.10.1.5 ("Hard Breach Supersedes Soft Breach") to also cover the Drawdown Gate. Only the highest-priority action's FLATTEN_ALL/status change is applied — the lower-priority path must not also fire a duplicate cancel/flatten or write a conflicting audit log entry for the same cycle.
(Source: QnA_init_docs.md A-20, extending BR_4.10.1.5)
BR_6.1.2.4: Required Margin — Futures dual-constraint calculation (canonical definition — ⚠️ calculation now owned by UC_6.1.3 Check 2)
⚠️ Moved. The full formula (Required_Margin = MAX(CME_Overnight_Margin, 25% × Notional) vs. Available_Equity), the multi-symbol CME_Overnight_Margin summing, the Rithmic Position_Notional_Value calculation, the Margin_Already_Encumbered_By_Other_Closed_Asset_Classes sub-procedure, and the asset-class scoping rules (already-closed / closing-now / not-yet-closing) are now specified in UC_6.1.3's Check 2 (CME Overnight Margin Check) — this UC no longer runs that calculation itself (see §5 Basic Flow step 5, which now dispatches to UC_6.1.3 unconditionally once Gate 1 passes). This anchor (BR_6.1.2.4) is kept as a pointer, not deleted, because the WBS deprecation note for the old UC_6.3 row (docs/BA/UC_6.1-6.3/index.md), UC_6.1.1 BR_6.1.1.5, and CHR-102's CR_summary.md all cite this exact anchor — they continue to resolve here, to the pointer, rather than breaking.
Per A-24 (BA decision, 2026-09-06), "Required Margin" still has a single canonical definition across the entire SRS — it just now lives in UC_6.1.3 instead of here. WBS's separate UC_6.3 ("Required margin") row remains deprecated and does not exist as a standalone UC; any future cross-reference to "Required Margin" logic should point to UC_6.1.3's Check 2, not here and not to a UC_6.3.
(Source: RFQ_ Stack Trading Prop Tech V7.pdf §Risk Enforcement Endpoints — "Futures Asset-Specific Margin Enforcement", lines 1733-1767; QnA_init_docs.md A-24; calculation relocated to UC_6.1.3 as Check 2 per user instruction (BA session), 2026-11-05)
BR_6.1.2.5: Forex 25% notional exposure cap — shared Table C config, universal Node.js dispatch (no native platform reliance)
Full formula, per-platform Total_Open_Forex_Notional sourcing (TraderEvolution direct field / MT5 calculated), and the unconditional dispatch enforcement path are specified in §5 Basic Flow steps 7-8.
Enforcement path change (CHR-102, client-confirmed 2026-09-15 — supersedes the former dual-path enforcement): the former "check native group leverage reduction, dispatch only if unavailable" branch (TraderEvolution) and the former "invoke the C++ MT5 Plugin to reduce leverage, no dispatch" branch (MT5) are both removed — both platforms now dispatch unconditionally.
(Source: CHR-102 — client-confirmed change, 2026-09-15; supersedes RFQ_ Stack Trading Prop Tech V7.pdf §Risk Enforcement Endpoints — "Forex Specific Enforcement", lines 1768-1794; QnA_init_docs.md A-26, A-27 — A-27's plugin-naming correction itself still stands, only its enforcement role changed)
BR_6.1.2.6: Halt/Session Open handling and notification payload construction
Full detail is specified in §5 Basic Flow steps 9-12 (Halt Start/End, Session Open restoration, and the shared payload-construction mechanism for every milestone).
(Source: RFQ_ Stack Trading Prop Tech V7.pdf §Risk Enforcement Endpoints — "Intraday Halt and New Session Open Operations" + "Notification Routing Logic", lines 1818-1870; QnA_init_docs.md Vòng 2 scope note)
BR_6.1.2.7: Native Broker Failsafe removed — no R|Admin dependency at T-30sec
Per CR-20260906-001, this UC does not own, configure, or depend on any T-30sec action. The former "Native Broker Failsafe Configuration" (Rithmic R|Admin "Time-Based Auto-Flatten" template) is fully removed from the architecture — R|Admin must not be configured with any Time-Based Auto-Flatten parameter for this purpose, and the Rithmic gateway does not auto-flatten on its own schedule. The T-30sec milestone UC_6.1.1 signals is consumed exclusively by UC_6.1.3's Node.js Active Failsafe. This closes A-22 (moot) and A-23 (reframed, no longer blocking) — no per-platform native failsafe (Rithmic, MT5, or TraderEvolution) is relied upon as the overnight-margin backstop; the Node.js middleware is universal across all three.
⚠️ Risk acceptance: removing the independent R|Admin hard failsafe means there is no backstop independent of the Node.js middleware itself — if the middleware crashes or hangs at T-30sec, nothing else runs. The client has accepted this tradeoff.
(Source: CR-20260906-001 — supersedes RFQ_ Stack Trading Prop Tech V7.pdf §"Native Broker Failsafe Configuration", lines 1795-1817; QnA_init_docs.md A-22, A-23)
BR_6.1.2.8: All enforcement timestamps are per-broker configurable variables, not hardcoded offsets
Every timestamp milestone this UC and UC_6.1.1 reference — T-60min, T-30min, T-10min, T-3min, T-2min, T-30sec, and (for Forex) Rollover_UTC itself — is a configuration value, not a value hardcoded into the enforcement logic. Each offset is stored as its own config variable (e.g. in a Table A/B/C-style config table, or an equivalent settings store), so that:
- Each offset can be changed independently (e.g. T-3min → T-5min for one asset class) without a code deployment.
- Each broker/platform (Rithmic, MT5, TraderEvolution) can carry its own value per milestone — the offsets are not required to be identical across platforms. For example, Rithmic's T-3min lockout offset and MT5's T-3min lockout offset are independently configurable, even though both currently default to the same 3-minute value.
- Any BA/Ops change to these values takes effect through config update, not a logic change to this UC or UC_6.1.1.
DST resolution is separate from this config layer — not a manual offset edit. Rollover_UTC's underlying wall-clock anchor (17:00 ET for Forex — common_rules.md §22.1) shifts between EST and EDT twice a year, but Ops/BA never edits a Rollover_UTC config value by hand to compensate — the EST⇄EDT transition is resolved automatically by the timezone-aware mechanism defined in UC_4.1.3 BR_4.1.3.5 (backend resolves the America/New_York IANA zone's local 17:00 every day, which natively yields the correct UTC instant in both EST and EDT). This UC and UC_6.1.1 only ever read the resulting pre-resolved Rollover_UTC/Official_Close_UTC timestamps — neither runs its own DST transition-date table or EST/EDT offset math. Futures' Official_Close_UTC is DST-resolved the same way but one layer further upstream — source-native at the CME Reference Data API itself (same BR_4.1.3.5), before UC_6.1.1's cron even writes it to CME_Instrument_Details.
(Source: user instruction, 2026-10-09; DST resolution per UC_4.1.3 BR_4.1.3.5, client-supplied verbatim, 2026-08-19)
BR_6.1.2.9: T-2min cycle completion broadcast + per-user execution alert
Full detail of the two mechanisms (Enforcement_Complete flow-level broadcast, and the 3-part per-user execution alert — POSITION_METRICS/ACCOUNT_METRICS auto-refresh, NOTIFICATION WebSocket, Overnight_Auto_Liquidation_Alert email) is specified in §5 Basic Flow step 12 and 12a.
⚠️ Not blocking: list_email.md's existing SES-19 trigger wording ("30 seconds prior to exchange lockout") describes only UC_6.1.3's T-30s failsafe case — it should be broadened to also cover this UC's own T-2min-driven liquidations/trims, since both use the same email.
BR_6.1.2.10: Client risk acceptance — imperfect overnight trim execution, firm capital prioritized over precision
The client has explicitly accepted that overnight margin/exposure enforcement cannot be dollar-perfect, and has set a standing priority rule for every case this UC dispatches into UC_6.1.3's TRIM_TO_COMPLIANCE loop (Required Margin shortfall, Forex notional shortfall, or any future trim dispatch from this UC):
| Case | Description |
|---|---|
| Risk acceptance — imperfect trim execution | "I am aware of the risks as the market is moving during the time we are calculating and sending orders. It does not have to be perfect to the dollar." The client accepts that Required_Margin/Target_Limit math and the resulting trim orders are computed against a snapshot that can be stale by the time the order fills — live market movement during calculation/dispatch means the post-trim position will not land exactly on Target_Limit to the cent, and this is an accepted characteristic of the system, not a defect. |
| Standing priority rule — firm capital over avoiding over-trimming | "We do not currently have a mechanism for this, so suggest the following rule. We never prioritize avoiding over-trimming over protecting firm capital. As I noted regarding network hiccups, if our connection is compromised, firm capital is at risk, and immediate hard liquidation is required." Whenever this UC's dispatch into UC_6.1.3 encounters a choice between risking an imprecise/over-sized trim and risking firm capital exposure, protecting firm capital always wins — the system must never hold off on FLATTEN_ALL just to avoid trimming more than strictly necessary. |
The resulting hard 2000ms Re-Check snapshot-query timeout that implements this priority rule is specified in UC_6.1.3 BR_6.1.3.7 — this UC does not itself run the Re-Check loop (that is UC_6.1.3's exclusive responsibility, consistent with CR-20260906-001's existing division of ownership), so the mechanism itself is not specified here.
(Source: user instruction, 2026-10-26 — client-provided risk-acceptance and priority-rule language, applied to UC_6.1.3's Re-Check step)
BR_6.1.2.11: Applies to both SIM and LIVE account types — no environment branching
This UC's entire overnight margin/exposure enforcement logic — the T-60/30/10min market-status warnings, the T-3min Pre-Close Lockout (both Layer 1 state/notification and Layer 2 broker-native mechanisms), the T-2min Universal Drawdown Safety Gate, the Futures Required Margin dual-constraint audit, the Forex 25% notional exposure sweep, the Halt/Session Open handling, and the per-user execution-alert mechanism (BR_6.1.2.9) — runs identically for SIM and LIVE account types. There is no SIM-only or LIVE-only branch anywhere in this UC's milestones, formulas, or dispatch logic:
- The same
Official_Close_UTC/Rollover_UTCtimeline thread (UC_6.1.1) drives both account types' enforcement cycles. - The same Required Margin formula (now UC_6.1.3's Check 2, BR_6.1.2.4) and Forex notional-cap formula (BR_6.1.2.5) apply regardless of whether the account is a SIM challenge/evaluation account or a funded LIVE account.
- Dispatch into UC_6.1.3's
TRIM_TO_COMPLIANCE/FLATTEN_ALLmechanism, and the client risk-acceptance/priority rule governing it (BR_6.1.2.10), is the same for both — a SIM account's overnight position is trimmed/flattened through the exact same Rithmic/MT5/TraderEvolution gateway dispatch path as a LIVE account's. - This is distinct from UI-layer concerns elsewhere in the SRS (e.g. UC_4.8.1 SIM / UC_4.12.2 LIVE having separate dashboard widgets that each surface this UC's broadcasts) — this UC's own backend enforcement logic has no such split.
(Source: user instruction, 2026-10-26 — BA note confirming this UC's enforcement scope covers both account types)
BR_6.1.2.12: Adam-confirmed universal fallback — any margin-calculation issue defaults to FLATTEN_ALL
The client (Adam) has set a standing, general-purpose fallback rule covering every margin/notional calculation this UC performs, not just the specific missing-CME-rate case already documented in Exc-2:
"At any time if you encounter issues with margin calculation, all fallback plans are FLATTEN_ALL."
Scope — applies to any calculation failure, not one enumerated list: this covers the Universal Drawdown Safety Gate's Total_Equity_Loss math (BR_6.1.2.2), the Futures Required Margin dual-constraint formula including the multi-symbol CME_Overnight_Margin sum and the Rithmic Position_Notional_Value calculation and the Margin_Already_Encumbered_By_Other_Closed_Asset_Classes sub-procedure (BR_6.1.2.4), and the Forex Total_Open_Forex_Notional sweep including its per-platform (TraderEvolution direct field / MT5 calculated) sourcing (BR_6.1.2.5) — any point in any of these where the required input is missing, unreachable, stale beyond a usable threshold, or the calculation itself throws/cannot complete. This is a standing principle this UC must apply going forward to failure modes not yet individually enumerated in this document, not a closed list limited to Exc-2's one worked case.
Why this matters distinctly from BR_6.1.2.10: BR_6.1.2.10's risk-acceptance/priority rule governs what happens once a shortfall has been correctly calculated and dispatched into UC_6.1.3's trim loop (imprecise trim execution, the Re-Check snapshot timeout). This rule (BR_6.1.2.12) governs the step before that — what happens when the Required Margin/notional figure itself cannot be reliably calculated in the first place. Both rules point to the same outcome (FLATTEN_ALL over any uncertain/partial action), from the client's same standing priority: firm capital protection over precision, applied at two different points in the pipeline.
(Source: user instruction, 2026-10-27 — Adam-confirmed requirement: "at any time if you encounter issues with margin calculation all fallback plans are FLATTEN ALL")
BR_6.1.2.13: Rithmic No Trading From/To daily sync cronjob — Rithmic only, separate from UC_6.1.1's CME-ingestion cron
[CR] Rithmic's Layer 2 No Trading From/To window (BR_6.1.2.1/§5 step 2's Rithmic bullet) cannot simply be configured once ahead of time the way TraderEvolution's "Liquidation Only" status or MT5's Close Only Trading Mode can — each whitelisted Futures symbol's close/open boundary shifts from day to day (different trading calendar per symbol, holidays, early closes), so the window itself must be re-pushed to Rithmic every day.
- A dedicated daily middleware cronjob pushes that trading day's close/open timestamps (
Official_Close_UTC/Session_Open_UTC) for every one of the ~31 whitelisted Futures symbols (UC_6.1.1CME_Whitelist) over to Rithmic, so the Adapter can set/refresh each symbol's own No Trading From/To window for that day's T-3min boundary. - This is a separate cronjob from UC_6.1.1's own 01:00 UTC CME-ingestion cron. UC_6.1.1's cron is a pure ingestion job — it pulls the trading calendar from the CME Reference Data API into
CME_Instrument_Details. This cronjob runs in the opposite direction — it pushes the already-ingested close/open timestamps fromCME_Instrument_Detailsout to Rithmic — and is not itself a step of UC_6.1.1's flow. - Rithmic only. Neither TraderEvolution nor MT5 needs an equivalent daily sync — their own Layer 2 lockout mechanisms (TE's instrument-level "Liquidation Only" status via a TE Scheduler task, MT5's
TRADE_CLOSEONLYgroup-symbol setting) are configured once ahead of time and do not carry a daily, per-symbol close/open boundary the way Rithmic's No Trading From/To window does. - Dependency, not a redundant data source. This cron consumes the same
Official_Close_UTC/Session_Open_UTCvalues UC_6.1.1 already committed for the day — it does not independently query CME itself. If UC_6.1.1's own cron has not yet run or failed for a symbol that day (see UC_6.1.1 Exc-1/rolling 14-day backup), this cron pushes whateverCME_Instrument_Detailscurrently holds for that symbol (fresh data or the rolling backup), rather than blocking on a fresh CME call of its own. - Exact run time and failure-handling behavior (retry policy, alerting if a push to Rithmic fails) are not yet specified — flagged as an open implementation detail pending BA/Ops confirmation; this BR records only that the sync must happen daily, per-symbol, and ahead of each symbol's own T-3min.
(Source: user request, 2026-11-06 — "mốc T-3 với cơ chế được set up tại Rithmic 'No trading from/No trading to' thì hàng ngày middleware phải thực hiện chạy 1 cronjob để đẩy lại mốc thời gian giờ đóng/mở cửa của 31 symbol lại sang sàn để adapter thực hiện set lại mốc thời gian cho logic T-3. (Cron job này chỉ áp dụng với Rithmic không liên quan đến TE và MT5)")
9. Update History
| Date | Version | Section | Change From | Change To | Source |
|---|---|---|---|---|---|
| 2026-09-06 | v1 | All (new) | UC_6.1.2 not yet written; WBS listed a separateUC_6.3 for Required Margin | Initial SRS for UC_6.1.2, with Required Margin (Futures dual-constraint + Forex 25% notional) fully merged in as the sole canonical definition per A-24 — no standalone UC_6.3 written | RFQ_ Stack Trading Prop Tech V7.pdf lines 1689-1870; CR-20260827-001; CR-20260906-001; QnA_init_docs.md A-20 → A-27 |
| 2026-09-06 | v1 | Whole document | Published together with UC_6.1.1/UC_6.1.3 in one combined file (UC_6.1.1-6.1.3_v1.md) | Split into 3 separate per-UC files per BA instruction; this file now contains UC_6.1.2 only; all cross-UC anchors rewritten to cross-file links | User instruction 2026-09-06 —"Hãy tách các UC_6.1.1, UC_6.1.2 và UC_6.1.3 ra thành 3 file UC riêng, không gộp vào 1 file." |
| 2026-09-09 | v1 | Exceptional Flows (Exc-2), §9-10 removed | Exc-2 was flagged⚠️ [ASSUMPTION — pending client confirmation], citing the old combined CR-20260906-001 §B.3; NFRs (old §9) and Acceptance Criteria (old §10) sections present | Exc-2 rewritten to mirrorUC_6.1.3's confirmed missing-risk-data failsafe language (BR_6.1.3.2, CHR-100) — no longer an open assumption; NFRs and Acceptance Criteria sections removed; Update History renumbered to §9 | User instruction 2026-09-09 |
| 2026-09-15 | v1 | Overview (Description, 3rd Party); §5 steps 5-11 (renumbered); §6 Alt-2 (removed); §7 Exc-3 (rewritten);BR_6.1.2.5 (full rewrite) | Forex 25% overnight notional cap relied on native platform mechanisms as the primary enforcement path: MT5 invoked the C++ MT5 Plugin to reduce leverage so the native Stop Out engine cleared the excess (no dispatch to UC_6.1.3); TraderEvolution checked native group leverage reduction first and only dispatched to UC_6.1.3 if unavailable. Alt-2 documented this native-leverage-reduction path; Exc-3 was conditioned on "neither native mechanism available" | Client confirmed neither MT5 nor TraderEvolution can be relied upon to natively enforce this exact 25% threshold. Both platforms now dispatchunconditionally to UC_6.1.3 as a TRIM_TO_COMPLIANCE call — the Node.js middleware itself calculates overage and dispatches market close orders directly via each platform's API (MT5 Gateway API / TraderEvolution Admin API), the same algorithmic loop used for Futures/Rithmic. No native-capability check gates the dispatch on either platform. Alt-2 removed entirely; Exc-3 reworded to apply universally (dispatch failure/lag on any of the 3 platforms). The universal T-30s Active Failsafe (BR_6.1.3.4, CHR-101) now applies to the MT5 Forex path too, since MT5 Forex now actually reaches UC_6.1.3. The C++ MT5 Plugin (STAGE2-019/A-27 naming correction) is not removed from the architecture — only demoted from primary enforcement path to a possible secondary/other-purpose role | CHR-102 — client-confirmed change, relayed by user (BA session) 2026-09-15 |
| 2026-09-17 | v1 | §5 Basic Flow (steps 1-11 expanded, step 11) | Steps 2, 4, 6 stated each formula (Total_Equity_Loss, Required_Margin/Available_Equity, Allowed_Notional) and then pointed to §8 (See [BR_6.1.2.2]/[BR_6.1.2.4]/[BR_6.1.2.5]) for what each variable means; steps 1, 3, 11 similarly deferred detail to §8 via See [BR_x] links | Every formula-bearing step now defines each of its own variables inline, directly beneath the formula, instead of sending the reader to §8; steps 1, 3, 11 have their full behavior stated in the step itself with noSee [BR_x] pointer. §8 Business Rules is unchanged and remains the authoritative, source-cited definition of each rule | User instruction 2026-09-17 —"update lại tài liệu thành từng step chi tiết, nếu step có công thức thì mô tả ý nghĩa từng thành phần ngay dưới, không mô tả theo phần refer tới business rule nữa" |
| 2026-10-08 | v1 | Overview (Description), §2 Trigger, §4 Post-conditions, §5 Basic Flow (new step 1, steps renumbered 2-12), §8 (BR_6.1.2.1 notification detail added; BR_6.1.2.2 IF/THEN pseudocode added; BR_6.1.2.4 Margin_Already_Encumbered_By_Other_Closed_Asset_Classes sub-procedure + Pass/Fail logic added; BR_6.1.2.5 IF/THEN pseudocode added; new BR_6.1.2.8 added) | T-60/30/10 market status warnings existed only asAlert_Level names in §5's notification step, with no dedicated Basic Flow step, Business Rule, Trigger entry, or Post-condition of their own. T-3min Lockout's Order Filter Rule/Authorized transactions/Notification detail (Widget_State/Widget_Short_Text/Severity/Copy) was in §5 only, not in BR_6.1.2.1. Futures Required Margin's Margin_Already_Encumbered_By_Other_Closed_Asset_Classes was defined as a one-line concept, with no sub-procedure breakdown. T-2min Drawdown Gate and Forex-exposure steps stated their formulas as plain assignments, not explicit IF/THEN branch logic | Rewrote per direct BA instruction, matching a supplied point-by-point description: added §5 step 1 (T-60min/T-30min/T-10min warnings, informational only) and newBR_6.1.2.8 — flagged as a gap since UC_6.1.1's derived timeline thread does not generate these 3 timestamps and neither does RFQ V7's own milestone-generation list, only the later Notification Routing Logic section names them. BR_6.1.2.1 now states the Order Filter Rule / Authorized transactions / Notification fields explicitly. BR_6.1.2.2 and BR_6.1.2.5 now show explicit IF ... => ... branch logic matching the source wording, alongside the existing prose. BR_6.1.2.4 now spells out the 5-step Margin_Already_Encumbered_By_Other_Closed_Asset_Classes sub-procedure (Snapshot Positions → Identify Closed Markets → Filter → Calculate Encumbered Margin → Sum) and explicit Pass/Fail branching. §2 Trigger and §4 Post-conditions updated to include the 3 new warning milestones. Existing BR numbers (BR_6.1.2.1 through BR_6.1.2.7) were not renumbered, since other UCs (UC_6.1.3, etc.) cross-reference them by exact number — the new rule was appended as BR_6.1.2.8 rather than inserted | User instruction 2026-10-08 |
| 2026-10-09 | v1 | Overview (Description), §5 Basic Flow (step 1 Futures/Forex timing split, step 2 broker-native mechanism + config note), §8 (BR_6.1.2.8 rewritten with Futures/Forex split; new BR_6.1.2.9, new BR_6.1.2.10) | T-60/30/10 were described as offsets fromOfficial_Close_UTC only, with no distinct Forex timing source. T-3min Pre-Close Lockout documented only this UC's own API-gateway order filter, with no mention of broker-native equivalents. No rule stated that milestone offsets are configurable, or that each broker can carry its own value per milestone | Per direct BA instruction: (1) §5 step 1 andBR_6.1.2.8 now split T-60/30/10 by asset class — Futures anchors to UC_6.1.1's cron-derived Official_Close_UTC timeline thread (unchanged), Forex anchors instead to a new Rollover_UTC (16:00 CT / 17:00 EST institutional rollover, same boundary BR_6.1.2.5 already references) — flagged as a gap pending a confirmed Rollover_UTC source. (2) §5 step 2 and new BR_6.1.2.9 document the client-suggested, not yet confirmed broker-native Pre-Close Lockout mechanisms per platform — TraderEvolution's instrument-level "Liquidation Only" status via a TE Scheduler task, MT5's Close Only Trading Mode (TradeMode = TRADE_CLOSEONLY), and Rithmic's No Trading From/To window — cross-referenced to the existing MT5_T2_T3_Margin_Enforcement_Mechanism_Comparison_v1.md and TE_Overnight_Margin_News_Event_Scheduler_Integration_v1.md analysis docs, both of which already flag this as pending/not a confirmed CR·QnA source; explicitly left open whether this UC's own gateway filter is kept as a redundant second layer or replaced by the broker-native setting. (3) New BR_6.1.2.10 confirms every milestone offset (T-60/30/10/3/2/30sec, Rollover_UTC) is a per-broker configuration value, not hardcoded, and that different brokers may carry different values for the same milestone — storage shape itself flagged as an open implementation decision. Existing BR numbers not renumbered; new rules appended as BR_6.1.2.9/10 | User instruction 2026-10-09 |
| 2026-10-12 | v1 | Overview (Description), §4 Post-conditions (new "liquidation/trim executed" + "T-2min cycle complete" entries), §5 Basic Flow (step 4, step 6, step 8, step 12 + new step 12a), §8 (newBR_6.1.2.11) | T-2min'sEnforcement_Complete and per-user execution notifications were not distinguished — step 12 only generically listed Enforcement_Complete among other milestone payload names, with no description of when/how a per-user liquidation alert fires, no mention of POSITION_METRICS/ACCOUNT_METRICS auto-refresh, and no reference to the NOTIFICATION WebSocket or the Overnight_Auto_Liquidation_Alert email at this UC's own T-2min steps | Per client confirmation:Enforcement_Complete is a flow-level broadcast firing every T-2min cycle regardless of outcome (unconditional). A separate, conditional per-user execution alert fires only when a liquidation (Drawdown Gate FLATTEN_ALL, step 4) or trim (UC_6.1.3 dispatch via steps 6/8, once actually filled) executes against a specific account — the T-2min margin calculation itself is silent and generates no notification on its own. New step 12a and BR_6.1.2.11 spell out the 3-part mechanism for that per-user alert: (1) POSITION_METRICS/ACCOUNT_METRICS WebSocket streams auto-detect the live close order and refresh the dashboard with zero Zapier involvement — this UC does not push these metrics itself; (2) the margin script fires a NOTIFICATION WebSocket event for the Notification Center entry; (3) the margin script separately triggers the Zapier webhook for the post-execution Overnight_Auto_Liquidation_Alert email (SES-19) via AWS SES. BR_6.1.2.11 also flags (not blocking) that list_email.md's existing SES-19 trigger wording ("30 seconds prior to exchange lockout," describing only UC_6.1.3's T-30s failsafe case) should be broadened to cover this UC's T-2min-driven liquidations/trims too, since both use the same email | User instruction 2026-10-12 — client-confirmed:"The system broadcasts Enforcement_Complete after the T-2 cycle finishes... A notification is only generated if the system actively executes a liquidation or trim on a specific trader's account... the standard POSITION_METRICS and ACCOUNT_METRICS WebSocket streams will automatically detect the flat position and refresh the UI... The margin script is only responsible for firing the NOTIFICATION WebSocket... and triggering the Zapier webhook for the post-execution Overnight_Auto_Liquidation_Alert email via AWS SES" |
| 2026-10-15 | v1 | §5 Basic Flow (step 2 — Layer 1/Layer 2 split + sandbox note); §8 (BR_6.1.2.1 cross-reference added; BR_6.1.2.4 Rithmic notional calculation added; BR_6.1.2.5 TE/MT5 notional sourcing added); §5 Basic Flow (steps 5, 7 — notional calculation detail) | Step 2 described the middleware's own API-gateway lockout and each platform's native mechanism in one undifferentiated list, with no explicit statement of which actor performs which action, and no sandbox testing note. Steps 5/BR_6.1.2.4 and 7/BR_6.1.2.5 referencedPosition_Notional_Value/Total_Open_Forex_Notional as inputs without specifying how either value is actually obtained from Rithmic, TraderEvolution, or MT5 | Per BA instruction: (1) §5 step 2 rewritten into an explicitLayer 1 (middleware, platform-agnostic) vs. Layer 2 (native, configured directly at each platform) split, with a new sandbox testing note — Layer 2 mechanisms (TE "Liquidation Only", MT5 Close Only Trading Mode, Rithmic No Trading From/To) can only be tested in sandbox against the single available Forex pair, USD-TRY; this limitation does not apply to Layer 1. BR_6.1.2.1 now cross-references this split. (2) §5 step 5 and BR_6.1.2.4 now specify Rithmic's total open-position notional dollar value calculation — no single ready-made field exists; computed from PnlInfo.Position, RefDataInfo.SinglePointValue, TradeInfo.Price/BidInfo.Price/AskInfo.Price, and RefDataInfo.Currency as Position_Notional = abs(Position × CurrentPrice × SinglePointValue), summed across positions. (3) §5 step 7 and BR_6.1.2.5 now specify Forex notional sourcing per platform: TraderEvolution exposes it directly via GET /accountDetails's totalPositionsValue field; MT5 has no equivalent field and the middleware must compute it from positions_get()/symbol_info() inputs (POSITION_VOLUME, POSITION_PRICE_CURRENT, SYMBOL_TRADE_CONTRACT_SIZE, SYMBOL_TRADE_CALC_MODE, SYMBOL_CURRENCY_BASE/SYMBOL_CURRENCY_PROFIT), summed across open positions | User instruction 2026-10-15, citing client (Adam Culver) field/API reference tables for Rithmic and MT5 notional calculation |
| 2026-10-26 | v1 | §5 Basic Flow (step 2 — Layer 1 corrected); §8 (BR_6.1.2.1 rewritten; new BR_6.1.2.12) | §5 step 2 andBR_6.1.2.1 described Layer 1 (the middleware's own T-3min action) as itself enforcing the Order Filter Rule and the Authorized-transactions list, alongside the Notification — duplicating what is actually Layer 2's (each broker-native mechanism's) job. No business rule existed documenting the client's stated risk acceptance for imprecise overnight trim execution, or any timeout on the TRIM_TO_COMPLIANCE loop's Re-Check portfolio-snapshot query | Per BA correction: Layer 1 is restated to doonly the Lockout_Active state update plus the milestone notification broadcast — the same pattern as T-60/30/10 (BR_6.1.2.8) — with the Order Filter Rule and Authorized-transactions enforcement moved entirely under Layer 2 (TraderEvolution/MT5/Rithmic native mechanisms), where it is actually enforced.BR_6.1.2.1 rewritten to match. New BR_6.1.2.12 records the client's risk acceptance that overnight trim execution cannot be dollar-perfect given market movement during calculation/dispatch, the standing priority rule that protecting firm capital always outweighs avoiding over-trimming, and a new hard 2000ms timeout on UC_6.1.3's Re-Check portfolio-snapshot query (Futures step 7 / Forex step 8) — if the snapshot does not return within 2000ms, the middleware treats the connection as compromised, aborts the trim loop, and fires FLATTEN_ALL. This is distinct from the existing 2000ms fill-confirmation timeout (UC_6.1.3 BR_6.1.3.5). The mechanism itself is specified in UC_6.1.3 (updated in the same session); this UC records only the client-stated risk-acceptance language and priority rule driving it | User instruction 2026-10-26 — BA correction on Layer 1/Layer 2 scope + client-supplied risk-acceptance quotes:"I am aware of the risks as the market is moving during the time we are calculating and sending orders. It does not have to be perfect to the dollar." / "We never prioritize avoiding over-trimming over protecting firm capital... Apply a hard 2000ms timeout to the Re-Check API snapshot query. If the middleware cannot retrieve the updated position snapshot within that window, assume the connection is compromised. Abort the trim loop immediately and fire the FLATTEN_ALL command." |
| 2026-10-26 | v1 | §5 Basic Flow (step 7 — MT5Position_Notional_Value rewritten); §8 (BR_6.1.2.5 MT5 sourcing note rewritten) | §5 step 7's MT5 sub-bullet andBR_6.1.2.5 described MT5's per-position notional as a generic volume × price_current × trade_contract_size calculation (adjusted for trade_calc_mode, converted via currency_base/currency_profit), without the explicit 3-case breakdown (quote=USD / base=USD / cross-pair) that UC_6.1.3's TRIM_TO_COMPLIANCE algorithm already uses for the same Position_Notional_Value figure, and no live-price requirement was stated here | Rewrote both to use thesame 3-case Position_Notional_Value formula as UC_6.1.3 BR_6.1.3.3 — Lot_Size × Contract_Size_Per_Lot × Current_Price when the quote currency is USD (e.g. EURUSD), Lot_Size × Contract_Size_Per_Lot when the base currency is USD (e.g. USDJPY), and Lot_Size × Contract_Size_Per_Lot × FX_Conversion_Rate(Base_Currency → USD) for a cross pair (e.g. EURGBP) — so the notional figure this UC sweeps against Allowed_Notional at T-2min and the notional figure UC_6.1.3 later trims against are computed identically, not via two independently-worded formulas for the same number. Added the same ⚠️ live-price requirement (Current_Price/FX_Conversion_Rate must be real-time from the MT5 Gateway API stream, never cached/delayed) that UC_6.1.3 already states. MT5 field mapping (POSITION_VOLUME, POSITION_PRICE_CURRENT, SYMBOL_TRADE_CONTRACT_SIZE, SYMBOL_CURRENCY_BASE/SYMBOL_CURRENCY_PROFIT) unchanged; TraderEvolution's direct totalPositionsValue sourcing unchanged | User instruction 2026-10-26 —"update cho tôi mô tả ở bước 7 tại T-2min của Forex, hãy mô tả lại công thức tính position notional value tương tự như thuật toán trim_to_compliance" |
| 2026-10-26 | v1 | Overview (new SIM/LIVE scope note); §8 (newBR_6.1.2.13) | This UC never explicitly stated whether its overnight margin/exposure enforcement applies to SIM accounts, LIVE accounts, or both — the only SIM/LIVE mentions in the document were incidental naming-collision cross-references (UC_4.8.1 SIM / UC_4.12.2 LIVE Defense Protocol naming, BR_6.1.2.2) | Added an explicit scope note in the Overview and newBR_6.1.2.13: this UC's enforcement logic (warnings, Pre-Close Lockout, Drawdown Gate, Required Margin audit, Forex notional sweep, Halt/Session Open, execution alerts) appliesidentically to both SIM and LIVE account types, with no environment branching anywhere in the milestones, formulas, or dispatch logic — matching the scope-note pattern already used elsewhere in the SRS (e.g. UC_4.7.1 BR_4.7.1.x, UC_5.8 BR_5.8.27) | User instruction 2026-10-26 —"Hãy note và mô tả rule cho tôi UC này áp dụng cho cả tài khoản ở sim và live." |
| 2026-10-26 | v1 | §5 Basic Flow (step 3Stop_Loss_Threshold note; step 5 multi-symbol CME_Overnight_Margin case); §8 (BR_6.1.2.4 multi-symbol note; BR_6.1.2.12 converted to table) | Step 3'sStop_Loss_Threshold bullet did not say where/when this per-account value is configured. Step 5's CME_Overnight_Margin bullet described a single symbol's margin requirement with no explicit statement of what happens when the trader holds multiple open Futures symbols at once. BR_6.1.2.12's risk-acceptance content was a flat bulleted list, not organized by case | (1) Step 3 andBR_6.1.2.2's cross-referenced context: Stop_Loss_Threshold is now described as the specific dollar figure already configured per account, assigned at account creation — either via a successful promotion (challenge/level-up) or a successful checkout flow (new purchase) — not a value re-derived or looked up against a shared constant at T-2min. (2) Step 5 and BR_6.1.2.4 now state explicitly that when multiple Futures symbols are open at once, CME_Overnight_Margin is the sum of each open symbol's own margin requirement (rate × contract count per symbol, added together), compared as one aggregate figure against the 25% × Notional leg — not evaluated symbol-by-symbol — with a worked example (MES $2,000 + MCL $400 = $2,400). (3) BR_6.1.2.12's four risk-acceptance items (risk acceptance, standing priority rule, new 2000ms timeout rule, mechanism ownership) converted from a bulleted list into a 2-column Case / Description table | User instruction 2026-10-26 —"Tại bước 3... chú thích mô tả của giá trị Stop_loss_threshold... lấy từ bộ giá trị theo từng tài khoản từ khi promotion hoặc tạo tài khoản từ flow checkout thành công" / "Tại bước 5... nếu hiện tại đang có nhiều position với nhiều symbol khác nhau được hold thì giá trị CME overnight margin sẽ là giá trị tổng của các symbol" / "Đối với các case risk acceptance hãy update mô thành dạng bảng chia thành từng case và description" |
| 2026-10-26 | v1 | §5 Basic Flow (step 4 race-condition bullet trimmed; Exc-1 trimmed); §8 (BR_6.1.2.1, .2, .4, .5, .6, .8, .11 trimmed to pointers; BR_6.1.2.9 removed) | Several Business Rules fully restated content already documented in §5 Basic Flow (or, forBR_6.1.2.3, in §7 Exc-1), creating duplicate maintenance points: BR_6.1.2.1/.2/.4/.5/.6/.8/.11 each repeated a formula, mechanism list, or notification sequence verbatim from a Basic Flow step; BR_6.1.2.3's priority-chain text was duplicated near-verbatim in §5 step 4 and §7 Exc-1, creating a 3-way duplicate with a circular "see BR_6.1.2.3"/"see Exc-1" risk; BR_6.1.2.9 fully duplicated BR_6.1.2.1/§5 step 2's Layer 2 mechanism list with no unique content and no source citation | Trimmed each duplicated BR down to a short pointer back to its Basic Flow step, keeping only content genuinely absent from the flow: BR_6.1.2.1 (pointer only), BR_6.1.2.2 (kept the SIM/LIVE naming-collision warning, trimmed the formula), BR_6.1.2.4 (kept the A-24/UC_6.3-deprecation note, trimmed the formula/sub-procedure), BR_6.1.2.5 (kept the CHR-102 supersession note, trimmed the formula/sourcing detail), BR_6.1.2.6 (pointer only), BR_6.1.2.8 (kept the RFQ sourcing-gap note, trimmed the Futures/Forex detail), BR_6.1.2.11 (kept thelist_email.md SES-19 wording-gap note, trimmed the 3-part mechanism). Resolved the BR_6.1.2.3/Exc-1 circularity by keeping the full priority-chain rule in BR_6.1.2.3 (its natural §8 home) and shortening Exc-1 and §5 step 4's race-condition bullet to point to it instead. Removed BR_6.1.2.9 entirely (merged into BR_6.1.2.1) — its number is intentionally left unused rather than reassigned, since BR_6.1.2.10–.13 are cross-referenced by exact anchor from this doc and from UC_6.1.3 (BR_6.1.2.12), and renumbering them would require updating those external links for no functional benefit. BR_6.1.2.3, .7, .10, .12, .13 left unchanged — verified as having no duplicate in §5/§6/§7 (or, for .3, now the sole canonical copy) | User instruction 2026-10-26 — "rà các business rule nếu đã có chú thích và mô tả ở các bước của basic flow hay là các alternative flow thì sẽ không mô tả lại thêm ở business flow nữa để tránh trùng" / "sau khi rà các business flow mô tả trùng thì hãy đánh lại số thứ tự cho đúng" — audited via subagent dispatch; renumbering scoped to removing the now-empty BR_6.1.2.9 slot rather than shifting .10–.13, per cross-reference-safety tradeoff confirmed with BA |
| 2026-10-26 | v1 | §8 (full renumber BR_6.1.2.10→.9, .11→.10, .12→.11, .13→.12; "removed" notice deleted); every internal cross-reference in §1 Overview, §4 Post-conditions, §5 Basic Flow updated to match; UC_6.1.3's 4 references to the old BR_6.1.2.12 updated to BR_6.1.2.11 | Following the prior pass, BR_6.1.2.9 had been removed and left as an intentional numbering gap (a short "removed" notice in its place), with .10–.13 kept at their original numbers specifically to avoid touching UC_6.1.3's 4 cross-references to BR_6.1.2.12. User explicitly asked for the gap to be closed by renumbering, with any resulting references corrected | Closed the gap: deleted the "removed" notice block; renumbered BR_6.1.2.10 (per-broker config timestamps) → BR_6.1.2.9, BR_6.1.2.11 (T-2min cycle completion + per-user execution alert) → BR_6.1.2.10, BR_6.1.2.12 (client risk acceptance / 2000ms Re-Check timeout) → BR_6.1.2.11, BR_6.1.2.13 (SIM/LIVE scope) → BR_6.1.2.12. Updated every internal link pointing to the old numbers: §1 Overview Description (2 links) and SIM/LIVE scope note (1 link), §4 Post-conditions (3 links), §5 Basic Flow steps 1/2/12/12a (5 links), and the cross-reference inside the renumbered SIM/LIVE rule itself. Updated UC_6.1.3's 4 occurrences of BR_6.1.2.12 (§6 Exc-5, §8 BR_6.1.3.7 body ×2, §9 Update History ×2) to BR_6.1.2.11, keeping both files' anchors in sync. §8 now runs BR_6.1.2.1–BR_6.1.2.12 consecutively with no gaps | User instruction 2026-10-26 — "Đánh lại số thứ tự cho đúng của business rule, nếu cần sửa lại tham chiếu thì hãy sửa lại cả phần đó" |
| 2026-10-26 | v1 | §5 Basic Flow step 7 (MT5Total_Open_Forex_Notional sourcing — 2 sentences corrected) | Step 7's MT5 sub-bullet said "the middleware (or the MT5 API layer) must calculate it itself" and "the middleware sums them across all open Forex positions" — attributing thePosition_Notional_Value calculation and the summation to the middleware, with the Adapter mentioned only parenthetically as an alternative | Corrected: for MT5, it is theAdapter (the MT5 API layer) that directly calculates and sums Position_Notional_Value across open positions to arrive at Total_Open_Forex_Notional — not the middleware. Both sentences reworded to name the Adapter as the actual actor performing this calculation, consistent with how Layer 1/Layer 2 and Adapter-vs-middleware responsibilities are already split elsewhere in this UC (e.g. §5 step 5's Rithmic notional calculation, also attributed to the Adapter) | User instruction 2026-10-26 — "Tại mô tả của công thức tính toán dữ liệu total open forex notional của MT5 thì dữ liệu được adapter trực tiếp tính toán chứ không phải là the middleware" |
| 2026-10-26 | v1 | §8 (BR_6.1.2.8 removed entirely; BR_6.1.2.11's "New rule" row removed); full renumber .9→.8, .10→.9, .11→.10, .12→.11; every internal cross-reference in §1/§4/§5 updated to match; UC_6.1.3's 2 references to the old BR_6.1.2.11 updated to BR_6.1.2.10 | (1) BR_6.1.2.8's content (Futures/Forex timing split for T-60/30/10) was already fully stated in §5 step 1, and its ⚠️ "sourcing gap" note was deemed unnecessary — T-60/30/10 map directly to RFQ V7's own Warning_60/Warning_30/Warning_10 payload names, so there is no real gap. (2) BR_6.1.2.11's risk-acceptance table carried a "New rule — hard 2000ms timeout on the Re-Check API snapshot query" row plus a dependent "Ownership of the mechanism" row, duplicating detail that belongs to UC_6.1.3's own BR_6.1.3.7 | Removed BR_6.1.2.8 entirely — §5 step 1 remains the sole home for the T-60/30/10 timing-split detail, with no BR pointer needed. In BR_6.1.2.11 (now .10), deleted the "New rule" row and its "Ownership" row, replacing both with one sentence noting the resulting 2000ms timeout is specified in UC_6.1.3 BR_6.1.3.7 — the table now holds only the two client-quote rows (imperfect-execution acceptance, firm-capital-priority rule). Renumbered the remaining §8 rules down one slot each (.9→.8 config-timestamps rule, .10→.9 per-user execution alert, .11→.10 risk acceptance, .12→.11 SIM/LIVE scope) and updated every internal link in §1/§4/§5 to match. Updated UC_6.1.3's 2 occurrences of the old BR_6.1.2.11 (Exc-5 body, BR_6.1.3.7 source line) to BR_6.1.2.10. §8 now runs BR_6.1.2.1–BR_6.1.2.11 consecutively with no gaps | User instruction 2026-10-26 — "Hãy update lại bỏ BR_6.1.2.8 và BR này không có source gap ở đây, các mốc T-60/30/10 tương đương với các tên warning_60/warning_30/warning_10 như ở doc FRQ v7. Sau đó đánh lại số thứ tự cho đúng." / "Tại BR_6.1.2.11, bỏ đi cho tôi mục new rule - hard 2000ms timeout on the Recheck API snapshot." |
| 2026-10-26 | v1 | §5 Basic Flow (step 3 — 2 worked examples added; step 5 — group-scoping note + worked example added; step 7 — worked example added) | Step 3 (Universal Drawdown Safety Gate) stated the formula andStop_Loss_Threshold sourcing with no worked numeric example for either asset class. Step 5 (Futures Required Margin) gave no explicit statement that Required_Margin is calculated only for the asset class currently at its own T-2min — not for every asset class/group the trader happens to hold positions in — and no full worked example tying the formula together end-to-end. Step 7 (Forex notional sweep) had no worked numeric example at all | (1) Step 3: added a Futures worked example ($50,000/$47,000 equity, Table B $5,000 threshold → gate passes) and a Forex worked example ($100,000/$92,500 equity, Table A $10,000 threshold → gate breaches), showing both outcome paths. (2) Step 5: added a 🔧 scoping note defining three groups relative to the asset class currently at T-2min — already-closed (feeds Margin_Already_Encumbered_By_Other_Closed_Asset_Classes only, no fresh Required_Margin), closing-now (the only group Required_Margin is actually computed for in that invocation), and not-yet-closing (excluded entirely — no charge, no encumbrance, awaits its own future T-2min) — plus a worked example spanning all three (GC closed/CL closing-now/ES not-yet-closing) tying CME_Overnight_Margin, Available_Equity, and the Pass/Fail branch together with concrete numbers. (3) Step 7: added a worked example ($100,000 equity × 25% = $25,000 Allowed_Notional; 0.5 lots EURUSD = $55,000 notional → breach → TRIM_TO_COMPLIANCE with Target_Limit = $25,000) | User instruction 2026-10-26 — "Hãy update mô tả thêm ở từng step tính toán ở 2 gate như T-2 thì mỗi step sẽ có ví dụ cụ thể riêng cho future và forex." / "Ở logic gate 2 của futures thì mô tả thêm case tại thời điểm tính toán mốc T-2 thì đang hold nhiều position và thuộc nhiều nhóm có các khung giờ đóng mở cửa khác nhau (nhóm đã đóng cửa/nhóm chuẩn bị đóng/nhóm chưa đến thời gian đóng cửa) thì ở các mốc này dữ liệu required margin sẽ không phải được tính toán cho tất cả các nhóm." |
| 2026-10-26 | v1 | §5 Basic Flow step 5 (25% × Notional/Account_Gross_Notional bullets — group scoping added) | The25% × Notional bullet and the Account_Gross_Notional definition described the platform/Adapter's notional sum as "every open Futures position"/"summed across the account's open Futures positions" — reading as an account-wide sum across all asset classes, inconsistent with the closing-now-group scoping just added to CME_Overnight_Margin on the other side of the same MAX(...) comparison | Clarified that the platform/Adapter's25% × Notional calculation is scoped identically to CME_Overnight_Margin — it sums Position_Notional_Value only across symbols belonging to the closing-now group (the asset class currently at its own T-2min), not the trader's entire open Futures book. Positions in the already-closed or not-yet-closing groups are excluded from this notional sum for the same reason they are excluded from CME_Overnight_Margin — they are not part of the Required Margin calculation this invocation of step 5 is running. Updated both the 25% × Notional bullet and the Account_Gross_Notional formula/example to state this explicitly | User instruction 2026-10-26 — *"Đối với công thức required margin hãy mô tả thêm cho tôi rằng việc tính toán giá trị notional trong 25%notional do platform tính toán cũng chỉ tính toán các position thuộc khung giờ đóng cửa đang tính của T-2." |
| 2026-10-26 | v1 | §4 Post-conditions ("Halt Start / Halt End" heading); §5 Basic Flow (steps 8-9 — Futures-only note added) | Neither the Post-conditions heading nor Basic Flow steps 8-9 (Halt_Start_UTC/Halt_End_UTC) stated that this milestone pair is Futures-only — it read as applying to both asset classes alongside the rest of this UC's milestones | Added an explicit note: Halt_Start_UTC/Halt_End_UTC are sourced from theCME_Instrument_Details table (a CME maintenance-window field that only exists for Futures instruments), so this milestone pair applies to Futures only. Forex currently has no equivalent maintenance-halt window — MT5/TraderEvolution do not publish a comparable scheduled-halt timestamp this UC can read — so steps 8-9 do not fire for Forex. §4's "Halt Start / Halt End" heading updated to flag this, and a ⚠️ sub-bullet added under each of steps 8 and 9 | User instruction 2026-10-26 — "Đối với mốc Halt_Start_UTC — Maintenance Freeze và Halt_End_UTC — Maintenance Unfreeze có thêm note cho tôi là mốc thời gian này chỉ áp dụng với Future vì hiện tại Forex đang không có khung thời gian này, dữ liệu khung thời gian bảo trì chỉ đang có là lấy được từ bảng CME instrument details áp dụng với luồng future thôi." |
| 2026-10-27 | v1 | §7 Exceptional Flows (Exc-2 generalized); new §8 BR_6.1.2.12 | Exc-2 only covered the one specific case of a missing CME overnight margin rate — there was no general, standing rule covering any other failure mode in the margin/notional calculation itself | Generalized Exc-2 into a universal fallback case covering any failure in the margin/notional calculation (BR_6.1.2.4/BR_6.1.2.5), not only the missing-CME-rate example, which is now presented as the first concretely identified instance rather than the whole rule. Added new BR_6.1.2.12 recording the client's (Adam) standing fallback rule verbatim: "At any time if you encounter issues with margin calculation, all fallback plans are FLATTEN_ALL." — distinguished from BR_6.1.2.11's risk-acceptance rule, which governs what happens after a shortfall is correctly calculated, whereas this new rule governs what happens when the calculation itself cannot be trusted in the first place | User instruction 2026-10-27 — Adam-confirmed requirement: "at any time if you encounter issues with margin calculation all fallback plans are FLATTEN ALL" |
| 2026-11-05 | v1 | §5 Basic Flow step 1 (Forex T-60/30/10 anchor), step 6 heading — removed hardcoded institutional rollover clock values | "16:00 CT / 17:00 EST" stated inline (2 occurrences) | Replaced with reset_time, cross-referenced to common_rules.md §22.1 — no clock value restated in this UC | User instruction, 2026-11-05 — consolidate all institutional-rollover/reset_time clock-value citations onto common_rules.md §22.1 as the single source of truth |
| 2026-11-05 | v1.1 | Overview (Description); §3 P-2; §4 Post-conditions ("Drawdown Gate passed" entry); §5 Basic Flow step 5 (rewritten); §8 BR_6.1.2.4 (rewritten as pointer); SIM/LIVE scope note (BR_6.1.2.4 cross-ref line) | For Futures, this UC's step 5 computed the full Required_Margin/Available_Equity dual-constraint audit itself (including the Margin_Already_Encumbered_By_Other_Closed_Asset_Classes sub-procedure) and only dispatched to UC_6.1.3 once, with a pre-computed Target_Limit, when that check failed | Architecture change, confirmed with user: for Futures, this UC's role at T-2min now ends at Gate 1 (Universal Drawdown Safety Gate) — once Gate 1 passes, it dispatches to UC_6.1.3 unconditionally (no shortfall pre-check, no pre-computed Target_Limit). UC_6.1.3 itself now runs a sequential two-check engine for Futures: Check 1 (25% ES-Equivalent Contract Cap, unchanged, CHR-100) then Check 2 (CME Overnight Margin Check — the exact Required_Margin/Available_Equity/Margin_Already_Encumbered_By_Other_Closed_Asset_Classes calculation this step used to run, now owned and detailed by UC_6.1.3). BR_6.1.2.4 rewritten as an explicit pointer to UC_6.1.3's Check 2 rather than deleted, since the WBS A-24 deprecation note (docs/BA/UC_6.1-6.3/index.md), UC_6.1.1 BR_6.1.1.5, and CHR-102's CR_summary.md all cite this exact anchor and must keep resolving. Forex is unchanged — this UC still computes its own 25% notional sweep and dispatches with a pre-computed Target_Limit, since Forex has no CME-margin/Check-2 concept. | User instruction (BA session), 2026-11-05 — detailed Futures algorithm description revealing Flow 24 now runs "Check 1" then "Check 2" sequentially inside UC_6.1.3's TRIM_TO_COMPLIANCE engine; architecture confirmed via clarifying questions before implementation |
| 2026-11-06 | v1.2 | §5 Basic Flow step 1 (Forex anchor bullet), step 6 heading; §8 BR_6.1.2.8 (new DST-resolution paragraph) | Rollover_UTC/reset_time was cross-referenced to common_rules.md §22.1 for its clock value (18:00 ET Futures / 17:00 ET Forex), but neither §22.1 nor this UC stated which mechanism actually resolves the EST⇄EDT (Daylight Saving Time) transition each year — readable as if this UC or UC_6.1.1 might need to run their own DST logic | Added explicit DST-resolution pointers: Forex's Rollover_UTC and the step 6 institutional-rollover heading now state the value is already DST-resolved before being consumed here, cross-referencing UC_4.1.3 BR_4.1.3.5 (Forex: timezone-aware library targeting America/New_York 17:00 local daily, auto-handles EST/EDT; Futures: resolved source-native by the CME Reference Data API before UC_6.1.1's cron even writes Official_Close_UTC). New paragraph added to BR_6.1.2.8 making explicit that DST is not a manual config edit on top of the per-broker timestamp config this BR already describes — it is a separate, automatic resolution step owned by BR_4.1.3.5, which this UC and UC_6.1.1 only consume the result of | User request, 2026-11-06 — "mô tả và update thông tin về khung giờ rollover đang áp dụng sẽ có xử lý DST trong UC_6.1.2 và UC_6.1.3"; DST mechanism itself already existed in BR_4.1.3.5 (client-supplied, 2026-08-19) and common_rules.md §22.1 (2026-11-05) — this update only adds the missing cross-reference from UC_6.1.2, it does not change the underlying DST mechanism |
| 2026-11-06 | v1.3 | §5 Basic Flow step 2 (Rithmic Layer 2 bullet — daily sync cronjob note added); §3 Pre-conditions (new P-5); new §8 BR_6.1.2.13 | Rithmic's No Trading From/To window (Layer 2, T-3min Pre-Close Lockout) was described as a static native configuration, like TraderEvolution's "Liquidation Only" status or MT5's Close Only Trading Mode — with no mention that, unlike those two, it must be re-synced to the exchange side daily since each symbol's close/open boundary shifts day to day | [CR] Added new BR_6.1.2.13: a dedicated daily middleware cronjob — separate from UC_6.1.1's own 01:00 UTC CME-ingestion cron — pushes that day's Official_Close_UTC/Session_Open_UTC for all ~31 whitelisted Futures symbols out to Rithmic, so the Adapter can set/refresh each symbol's own No Trading From/To window for that day's T-3min boundary. Explicitly Rithmic-only — TraderEvolution/MT5 need no equivalent daily sync, since their Layer 2 mechanisms are configured once ahead of time with no daily per-symbol boundary to refresh. §5 step 2's Rithmic bullet and new §3 P-5 cross-reference this new BR; exact cron run time and failure/retry handling flagged as an open implementation detail pending BA/Ops confirmation | User request, 2026-11-06 — "mốc T-3 với cơ chế được set up tại Rithmic 'No trading from/No trading to' thì hàng ngày middleware phải thực hiện chạy 1 cronjob để đẩy lại mốc thời gian giờ đóng/mở cửa của 31 symbol lại sang sàn để adapter thực hiện set lại mốc thời gian cho logic T-3. (Cron job này chỉ áp dụng với Rithmic không liên quan đến TE và MT5)" |