SRS: UC_6.2.1 — Flow 23: News Events
| BA in Charge | Date Created | Version | Document References |
|---|---|---|---|
| BA Team | 2026-09-06 | v1.1 | RFQ_ Stack Trading Prop Tech V7.pdf; Zapier Integration V7.pdf; CHR_67; UC_4.7.1 BR_4.7.1.4; UC_6.1.2 BR_6.1.2.2/BR_6.1.2.5/A-25/A-26 |
UC_6.2.1 — Flow 23: News Events
This UC owns Flow 23's T-30/T-10/T-1/T+1 broadcast sequence (Slack, Discord, and the Dashboard Notification Center — all three dispatched in parallel from the same event, see BR_6.2.1.3), the ingestion/filtering logic (Finnhub cron-poll trigger, Filter 1
Impact_Level, Filter 2 Futures/Forex currency-relevance breakdown — see BR_6.2.1.1/BR_6.2.1.2, confirmed by CHR_67), and thePOST /enforce-news-eventenforcement logic (Universal Drawdown check — the sameTotal_Equity_Loss ≥ 70% × Stop_Lossgate as UC_6.1.2's T-2min Drawdown Safety Gate, run here on-demand at T-1min →FLATTEN_ALL; asset-specific size caps →TRIM_TO_COMPLIANCE; each action also triggers a per-userNews_Liquidation_Alertemail, BR_6.2.1.8). It does not own the Dashboard Notification Center's own display/rendering of these entries (bell badge, dropdown list, filter tabs) — that remains UC_4.7.1's scope, which documents the same CHR_67-confirmed filter logic from its own display-side perspective, not a conflicting second definition. This UC also does not own Flow 24 / the Notification Matrix (UC_6.2.2 — separate provider, separate CR scope per CHR_67's "Not Affected" note).⚠️ SIM/LIVE scope split: the T-30/T-10/T+1 broadcast sequence (Global Alert + Notification Center warnings) goes out to both SIM and LIVE traders alike — it is informational only and carries no account-level action. The T-1min enforcement calculation itself — the Universal Drawdown check (BR_6.2.1.4) and the asset-specific size-cap check (BR_6.2.1.5), and the
FLATTEN_ALL/TRIM_TO_COMPLIANCEactions they dispatch — applies to LIVE accounts only. A SIM account is not flattened or trimmed by this UC's T-1min news-event enforcement. See BR_6.2.1.9.
1. Overview
| Field | Content |
|---|---|
| ID | UC_6.2.1 |
| Use Case | Flow 23 — News Event Manager (Finnhub cron-poll): T-30/T-10/T-1/T+1 broadcast sequence + /enforce-news-event enforcement (Universal Drawdown check, Futures/Forex size caps) |
| Description | A scheduled cron job continuously polls Finnhub's news API. Each qualifying high-impact news event (filtered by Filter 1 Impact_Level/Filter 2 currency-relevance, see BR_6.2.1.1/BR_6.2.1.2) drives Global Alerts to Slack & Discord and a simultaneous Notification Center push at T-30min and T-10min (Warning) — broadcast to both SIM and LIVE traders — then at T-1min marks the protocol Active and calls the Middleware Hub's POST /enforce-news-event endpoint. The endpoint's enforcement calculation applies to LIVE accounts only (BR_6.2.1.9): it runs a Universal Drawdown check across all LIVE users (Futures & Forex) — the same gate UC_6.1.2 runs at T-2min, here evaluated on-demand at T-1min — if a user's Total_Equity_Loss (Account_Starting_Equity − Current_Account_Equity) reaches or crosses Market_Loss_When_Stopped × swap_risk_threshold (70%), that user is flattened immediately (FLATTEN_ALL) regardless of asset class. Only for LIVE users who pass the Drawdown check does the endpoint apply asset-specific size caps — Forex notional (scoped to news-relevant positions only) vs. Max_Forex_Notional × cap_percent, Futures contracts (ES-Equivalent, Appendix C) vs. Floor(Max_Contracts_ES_Equiv × cap_percent) — trimming (TRIM_TO_COMPLIANCE) anyone over their cap. All flatten/trim actions execute in parallel, non-blocking batches, and each triggers a News_Liquidation_Alert email (SES-18) to the affected trader. At T+1min, a "Protocol Complete" Global Alert + Notification Center push closes the cycle, again broadcast to both SIM and LIVE. |
| Zapier Flow | Flow 23 — News Event Manager (Finnhub cron-poll) |
| Zapier Table | Table A (Forex — Max_Forex_Notional, absolute stop-loss threshold) · Table B (Futures — Max_Contracts_ES_Equiv, Appendix B, absolute stop-loss threshold) · Table C (shared cap_percent/swap_risk_threshold config, A-26 — same 25%/70% variables as UC_6.1.2's Drawdown Gate and Required Margin math) · Appendix C — Futures Relative Risk Helper Table (symbol → ES_Equivalent_Weight, Backend master data, UC_6.1.3 BR_6.1.3.1), used to convert the trader's open Futures book into ES-Equivalent units for Gate 2's size-cap check |
| 3rd Party | Finnhub — high-impact economic news provider, replacing the RFQ/Zapier baseline's illustrative "FXStreet" example, per CHR_67 · Discord · Slack (#risk-ops summary, plus the Global Alert channels) · Rithmic / MT5 / TraderEvolution execution gateways (flatten/trim dispatch, same gateways as UC_6.1.2/UC_6.1.3) |
No wireframe — backend automation + enforcement engine. Its T-30/T-10/T-1/T+1 checkpoints dispatch to Slack/Discord and the Dashboard Notification Center at the same time (BR_6.2.1.3) — the Notification Center's own bell-icon/dropdown rendering of those NC-RISK-01–NC-RISK-04 entries remains UC_4.7.1's scope.
2. Trigger
Scheduler-driven (cron poll), not webhook. A scheduled job actively calls Finnhub's news API on a fixed polling interval, continuously, so the system always has the latest Event Name / Impact_Level / Timestamp / Currency payloads without depending on Finnhub pushing anything. Each poll cycle's results run through Filter 1 (Impact_Level == "High") and Filter 2 (currency-relevance — Futures/Forex breakdown) directly in this UC (see BR_6.2.1.1 for the polling architecture, BR_6.2.1.2 for the full filter/mapping logic). Events that pass both filters are persisted to the news-event store and drive the T-30/T-10/T-1/T+1 sequence below.
3. Pre-conditions
| ID | Condition |
|---|---|
| P-1 | The cron poll job is running and reachable against Finnhub's API (BR_6.2.1.1); a news event has already passed Filter 1 + Filter 2 (BR_6.2.1.2) and is persisted in the news-event store. |
| P-2 | Account_Starting_Equity/Current_Account_Equity, Market_Loss_When_Stopped (Table A/B absolute stop-loss threshold), and swap_risk_threshold (0.70) are readable for the Universal Drawdown check — the same values and formula already used by UC_6.1.2 BR_6.1.2.2's Drawdown Gate. LIVE-only (BR_6.2.1.9) — not evaluated for SIM accounts. |
| P-3 | Max_Forex_Notional (Table A) and Max_Contracts_ES_Equiv (Table B, Appendix B) are readable for the asset-specific size-cap check, along with the shared cap_percent (0.25, Table C, A-26) and the Appendix C — Futures Relative Risk Helper Table (symbol → ES_Equivalent_Weight, UC_6.1.3 BR_6.1.3.1) used to convert the trader's open Futures book into ES-Equivalent units. LIVE-only (BR_6.2.1.9) — not evaluated for SIM accounts. |
| P-4 | The Rithmic / MT5 / TraderEvolution execution gateways are reachable for parallel-batch flatten/trim dispatch. LIVE-only (BR_6.2.1.9) — SIM accounts are not dispatched to these gateways by this UC. |
4. Post-conditions
T-30min / T-10min (Warning)
- A Global Alert is sent to Slack & Discord: "News Warning: [Event] in 30 mins" / "...in 10 mins". In the same dispatch, a Notification Center entry (
NC-RISK-01/NC-RISK-02, severityWARN) is pushed to every affected trader — both SIM and LIVE (BR_6.2.1.9) — see BR_6.2.1.3. No account-level action yet.
T-1min (Active) — Universal Drawdown check breached (LIVE accounts only — BR_6.2.1.9)
- The LIVE user is flattened immediately (
FLATTEN_ALL) — all working orders cancelled, all open exposure cleared, regardless of asset class. The asset-specific size-cap check does not run for this user this cycle (moot — the account is already flat). ANews_Liquidation_Alertemail (SES-18) is sent to the affected trader — see BR_6.2.1.8. A SIM account'sTotal_Equity_Lossis not evaluated against this check and is never flattened by it.
T-1min (Active) — Universal Drawdown check passed, size cap breached (LIVE accounts only — BR_6.2.1.9)
- Forex:
TRIM_TO_COMPLIANCEdispatched withTarget_Limit = Max_Forex_Notional × cap_percent(checked againstCurrent_Notional, scoped to news-relevant positions only — see BR_6.2.1.5). - Futures:
TRIM_TO_COMPLIANCEdispatched withTarget_Limit = Floor(Max_Contracts_ES_Equiv × cap_percent)(ES-Equivalent — checked againstOpen_Contracts_ES_Equiv, see BR_6.2.1.5). - A
News_Liquidation_Alertemail (SES-18) is sent to the affected trader — see BR_6.2.1.8. - A SIM account's position size is not evaluated against this cap and is never trimmed by it.
T-1min (Active) — both checks pass (LIVE accounts only)
- No action for that LIVE user; a Global Alert "News Protocol Active. Holding Limits Enforced." is still broadcast at the flow level (not per-user, and received by SIM traders too as an informational alert) paired with a
NC-RISK-03Notification Center entry (severityCRITICAL) — see BR_6.2.1.3.
T+1min (Complete)
- A Global Alert is sent: "News Protocol Complete. Trading Resumed." A summary (
scanned/actionscounts, LIVE accounts only) is posted to Slack#risk-ops, paired with aNC-RISK-04Notification Center entry (severityINFO) pushed to both SIM and LIVE — see BR_6.2.1.3.
5. Basic Flow
This flow merges the Zapier-flow-level description (Zapier Integration V7.pdf §Flow 23, lines 2206-2239) with the endpoint-level formalization (RFQ_ Stack Trading Prop Tech V7.pdf §Risk Enforcement Endpoints — "Enforce News Event", lines 1628-1656). Both describe the same enforcement action; the endpoint-level spec is used as the canonical formula wherever the two differ in precision — e.g. the Zapier doc's shorthand IF Abs(P&L) > Stop_Threshold → FLATTEN_ALL (Stop_Threshold "from Table C") is read as a flow-level paraphrase of step 4's more precise formula below, which is itself corrected to the same Total_Equity_Loss/Market_Loss_When_Stopped/swap_risk_threshold formula as UC_6.1.2's T-2min Drawdown Gate, not a conflicting second definition.
-
Cron poll — ingest and filter. On each fixed-interval cron tick, the scheduler calls Finnhub's news API and receives a batch of events (Event Name, Impact_Level, Timestamp, Currency) — this is an outbound poll, not an inbound webhook, so the system always has the latest events regardless of whether Finnhub pushes anything. Each event runs through two filters, in order:
Filter 1 — Impact level IF Event.Impact_Level != "High": Discard event (no further processing)Event.Impact_Level— Finnhub's own severity rating for the news item. Only events rated"High"proceed to Filter 2; medium/low-impact events are dropped here.
Filter 2 — Currency relevance Futures: IF Event.Currency == "USD": Relevant to all Futures traders (auto-relevant, no per-trader lookup) Forex: FOR each trader's open positions: IF Event.Currency == position.Base_Currency OR Event.Currency == position.Quote_Currency: Relevant to this traderEvent.Currency— the currency the news event is denominated in (e.g."USD","EUR","GBP").- Futures leg — since all whitelisted Futures instruments are USD-domiciled, any
"USD"event is relevant to every Futures trader with no per-trader lookup needed. - Forex leg — relevance is trader-specific and evaluated dynamically, with no static whitelist:
position.Base_Currency/position.Quote_Currencyare the two currencies making up each of that trader's currently open Forex positions (e.g. a trader holdingEURUSDhasBase_Currency = EUR,Quote_Currency = USD). An event is relevant to that trader only if itsEvent.Currencymatches either side of at least one of their open positions — e.g. a high-impact"EUR"or"USD"event is relevant to a trader holdingEURUSD, but a high-impact"GBP"event is not, unless they also hold aGBP-denominated position.
Events passing both filters are persisted to the news-event store and scheduled onto the T-30/T-10/T-1/T+1 timeline below.
-
T-30min — First Warning. Global Alert to Slack & Discord: "News Warning: [Event] in 30 mins", dispatched together with a Notification Center push (
NC-RISK-01,WARN) to every affected trader over theNOTIFICATIONWebSocket channel — both SIM and LIVE (BR_6.2.1.9). -
T-10min — Second Warning. Global Alert to Slack & Discord: "News Warning: [Event] in 10 mins", dispatched together with a Notification Center push (
NC-RISK-02,WARN) — both SIM and LIVE. -
T-1min — Protocol Active, call
/enforce-news-event. Global Alert "News Protocol Active. Holding Limits Enforced." is broadcast to Slack & Discord together with a Notification Center push (NC-RISK-03,CRITICAL) — again to both SIM and LIVE traders — and the Middleware Hub callsPOST /enforce-news-eventwithasset_class,impact_type("High"),stop_threshold/swap_risk_threshold(0.70),cap_percent(0.25). This checkpoint's broadcast is unconditional — it fires at the flow level regardless of whether any individual user actually ends up being flattened/trimmed in steps 4-5 below. ⚠️ The/enforce-news-eventcalculation itself (steps 4-5 below) evaluates LIVE accounts only — BR_6.2.1.9. SIM accounts receive this broadcast but are not evaluated by, or acted on through, the enforcement endpoint. -
Universal Drawdown check (ALL LIVE users, Futures & Forex — BR_6.2.1.9). For each LIVE user, the endpoint evaluates the same Total-Equity-Loss-vs-70%-Stop-Loss formula as UC_6.1.2's Universal Drawdown Safety Gate (BR_6.1.2.2), evaluated here at T-1min instead of T-2min:
Total_Equity_Loss = Account_Starting_Equity − Current_Account_Equity IF Total_Equity_Loss ≥ Market_Loss_When_Stopped × swap_risk_threshold: Action: FLATTEN_ALLAccount_Starting_Equity— the account's equity fixed at the start of the trader's current challenge/level (A-25) — not reset daily, and not the equity at the start of today's session.Current_Account_Equity— the account's real-time equity value at the moment this T-1min check runs.Total_Equity_Loss— the resulting dollar loss accumulated since the challenge/level began, tested against the 70% threshold below. This is cumulative loss since challenge/level start, not the instantaneous unrealized P&L of whatever positions happen to be open right now — same metric UC_6.1.2 tests at T-2min. This check is evaluated per user, not per asset class: a user who breaches via their Futures book alone still has both Futures and Forex exposure flattened.Market_Loss_When_Stopped— the absolute stop-loss dollar threshold configured for that asset class, looked up from Table A (Forex) or Table B (Futures) — the same value UC_6.1.2 callsStop_Loss_Threshold; same column, two documents' naming.swap_risk_threshold— the 0.70 (70%) ratio applied against that stop-loss threshold; the same 70% ratio UC_6.1.2 uses for its Drawdown Gate.Market_Loss_When_Stopped × swap_risk_threshold— the dollar boundary this gate tests against. IfTotal_Equity_Lossreaches or crosses it, the check breaches and the user is flattened immediately; the asset-specific size-cap check in step 5 does not run for this user this cycle since the account is already flat.- This evaluation loop iterates LIVE users only — SIM accounts are excluded from the scan entirely at this step, not merely exempted from the resulting action.
- This is the same gate, evaluated at a different checkpoint — UC_6.1.2 runs it on a fixed overnight schedule at T-2min; this UC runs it on-demand at T-1min whenever a qualifying news event fires. A trader whose
Total_Equity_Lossis already past the 70% line when a news event hits is flattened here regardless of whether the overnight T-2min cycle has run yet that day. - Worked example — Futures (check passes):
Account_Starting_Equity = $50,000,Current_Account_Equity = $47,000→Total_Equity_Loss = $50,000 − $47,000 = $3,000. Table BMarket_Loss_When_Stopped = $5,000→70% × $5,000 = $3,500. Since$3,000 < $3,500, the check passes — this trader proceeds to step 5's Futures contract-count cap. - Worked example — Forex (check breaches):
Account_Starting_Equity = $100,000,Current_Account_Equity = $92,500→Total_Equity_Loss = $100,000 − $92,500 = $7,500. Table AMarket_Loss_When_Stopped = $10,000→70% × $10,000 = $7,000. Since$7,500 ≥ $7,000, the check breaches —FLATTEN_ALLis dispatched immediately for this trader, and step 5's Forex notional cap does not run for them this cycle (moot — the account is already flat).
-
Asset-specific size caps — only for LIVE users who passed step 4.
Forex: Allowed = Max_Forex_Notional × cap_percent IF Current_Notional > Allowed: TRIM_TO_COMPLIANCE, Target_Limit = Allowed Futures: Final_Allowed_ES_Equiv = Floor(Max_Contracts_ES_Equiv × cap_percent) IF Open_Contracts_ES_Equiv > Final_Allowed_ES_Equiv: TRIM_TO_COMPLIANCE, Target_Limit = Final_Allowed_ES_Equiv-
Max_Forex_Notional— the account's maximum allowed Forex notional exposure, configured in Table A. -
cap_percent— the shared 25% cap config value in Table C (A-26); the same variable reused by UC_6.1.3's Futures Required Margin notional leg (Check 2) and UC_6.1.2's Forex exposure cap, not an independent News-Events-only constant. -
Allowed— the resulting dollar ceiling on Forex notional the trader may hold through the news event; compared againstCurrent_Notional. -
Current_Notional(Forex) — scoped to news-relevant positions only, not the account's entire Forex book. This check runs per news event, and a trader may be holding several open Forex positions at once, only some of which share a currency leg with the event that just triggered Filter 2 (BR_6.2.1.2).Current_NotionalsumsPosition_Notional_Valueonly across the positions Filter 2 flagged as relevant to this event (i.e.Event.Currency == position.Base_Currency OR position.Quote_Currency) — a position in an unrelated pair that happens to also be open is excluded from this sum, even though it remains open and uncapped by this particular news event's enforcement pass. Each relevant position's own notional is computed with the same 3-case formula UC_6.1.3BR_6.1.3.3uses (the same formula, not a separate one):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.Contract_Size_Per_Lot— the standard contract size for one lot (typically 100,000 units of the base currency for a standard lot).Current_Price— the pair's live current market price at calculation time — never a cached or stale rate.FX_Conversion_Rate(Base_Currency → USD)— for a cross pair (neither leg is USD), the live conversion rate from the position's base currency to USD.Current_Notional = Σ Position_Notional_Valueacross every open Forex position that Filter 2 flagged as relevant to the triggering event — not the sum of every open Forex position on the account.
-
Max_Contracts_ES_Equiv/Open_Contracts_ES_Equiv(Futures) — both sides of the cap comparison are converted into the same ES-Equivalent unit before being compared, never compared as raw contract counts. A trader's open Futures book can span multiple symbols with very different per-contract risk (e.g.40 MESmicro-index contracts vs3 ESfull-size contracts) — comparing raw contract counts against a rawMax_Contractsceiling would treat a Micro contract and a full-size contract as equally "one contract," which they are not. Both terms of this check are therefore expressed in ES-Equivalent units, using the same Appendix C — Futures Relative Risk Helper Table conversion that UC_6.1.3BR_6.1.3.1defines:Max_Contracts_ES_Equiv— the account's level/title-based ES-Equivalent contract ceiling from Table B (Appendix B — Futures Configuration Matrix), already expressed in ES-Equivalent units (e.g. an Associate Trader's8 Microsrow is0.8 ES-Equivalent), not a raw contract count.Open_Contracts_ES_Equiv— the trader's actual open Futures exposure, summing every open Futures position's raw contract count multiplied by that symbol'sES_Equivalent_Weightfrom Appendix C, across all open Futures symbols — not the raw sum of contracts across symbols.Final_Allowed_ES_Equiv = Floor(Max_Contracts_ES_Equiv × cap_percent)— 25% of the account's ES-Equivalent contract ceiling, rounded down to the nearest whole ES-Equivalent unit; compared againstOpen_Contracts_ES_Equiv, not against a raw contract count.
-
The
TRIM_TO_COMPLIANCEcall itself (sort algorithm, event-driven fill confirmation, failsafe timeout) is UC_6.1.3's exclusive scope — this UC only computesTarget_Limitand dispatches. -
Worked example — Forex:
Max_Forex_Notional(Table A) =$200,000,cap_percent = 25%→Allowed = $200,000 × 0.25 = $50,000. The triggering event is a high-impactUSDrelease. The trader holds two open positions:EURUSD(news-relevant —USDleg matches) withPosition_Notional_Value = $62,000, andAUDNZD(not news-relevant — neither leg isUSD) withPosition_Notional_Value = $30,000.Current_Notional = $62,000(theAUDNZDposition is excluded — it is not relevant to this event). Since$62,000 > $50,000, the cap is breached —TRIM_TO_COMPLIANCEis dispatched withTarget_Limit = $50,000; theAUDNZDposition is left untouched by this news event's enforcement pass. -
Worked example — Futures:
Max_Contracts_ES_Equiv(Table B) =0.8 ES-Equivalent(Associate Trader's8 Microsrow),cap_percent = 25%→Final_Allowed_ES_Equiv = Floor(0.8 × 0.25) = Floor(0.2) = 0.2 ES-Equivalent. Trader holds8 MES(weight0.1, Appendix C) →Open_Contracts_ES_Equiv = 8 × 0.1 = 0.8 ES-Equivalent. Since0.8 > 0.2, the cap is breached —TRIM_TO_COMPLIANCEis dispatched withTarget_Limit = 0.2(ES-Equivalent); UC_6.1.3's own algorithm converts this ES-EquivalentTarget_Limitback into the raw contract count to actually close.
-
-
Parallel batch execution. All
FLATTEN_ALL/TRIM_TO_COMPLIANCEactions from steps 4-5 execute concurrently in non-blocking batches for millisecond latency — one user's action is never serialized behind another's, even across a large batch of simultaneously-affected accounts. -
Per-user liquidation email. For every user against whom step 4 or step 5 dispatched an action (
FLATTEN_ALLorTRIM_TO_COMPLIANCE), the system sends that trader a liquidation email: Email IDSES-18, template keyNews_Liquidation_Alert, triggered by the automated flatten/trim, sent to the affected trader, containing an urgent notice detailing the automated position action along with the triggering event's name and timestamp. This is a per-user notification distinct from the flow-level Slack/Discord + Notification Center broadcasts — it only fires for a user who was actually acted on, not for every trader who merely received the T-1min "Protocol Active" alert. -
Endpoint output + Slack summary. The endpoint returns
{ "scanned": int, "actions": [...] }—scannedis the count of LIVE users evaluated,actionsthe list of flatten/trim actions dispatched against them. (Zapier Integration V7.pdf's flow-level description paraphrases this same response as{ "traders_processed": X, "liquidations_triggered": Y }— read as descriptive labels for the same two figures, not a second, conflicting field set.) Because steps 4-5 run the Universal Drawdown check and the size caps separately per asset class, the endpoint computestraders_processed/liquidations_triggeredonce per asset class (Futures, Forex) rather than one pooled figure, and the Slack summary posted to#risk-opspresents them as two separate blocks:
** [News event] Futures / Forex Liquidation Execution Summary** Future Summary: Traders Processed: {traders_processed} traders Liquidations Triggered: {liquidations_triggered} traders Forex Summary: Traders Processed: {traders_processed} traders Liquidations Triggered: {liquidations_triggered} traders
- `traders_processed` (X) — the number of LIVE traders this run of the endpoint scanned for that asset class (Futures block = all LIVE Futures traders scanned; Forex block = all LIVE Forex traders scanned). This is `scanned` for that asset class — every LIVE trader the Universal Drawdown check ([BR_6.2.1.4](#BR_6.2.1.4)) evaluated this cycle, regardless of outcome (breached, size-cap-trimmed, or fully compliant).
- `liquidations_triggered` (Y) — the number of traders in that asset class against whom an action was actually dispatched: either `FLATTEN_ALL` (step 4 breach) or `TRIM_TO_COMPLIANCE` (step 5 size-cap breach). This is the size of the Futures-scoped or Forex-scoped slice of `actions`. A trader who passed both checks (Alt-1) is counted in `traders_processed` but not in `liquidations_triggered`.
- `liquidations_triggered ≤ traders_processed` always — it is a subset count, not an independent figure. A quiet news event (no breaches, no size-cap trims) posts `Liquidations Triggered: 0 traders` on both blocks while `Traders Processed` still reports the full scanned population.
- This Slack summary is distinct from the T-30/T-10/T-1/T+1 Global Alerts ([BR_6.2.1.3](#BR_6.2.1.3)), which go to the Global Alert channels (Slack & Discord) rather than `#risk-ops` specifically, and carry no numeric breakdown — only this `#risk-ops` summary reports `traders_processed`/`liquidations_triggered` figures.
9. **T+1min — Protocol Complete.** Global Alert: *"News Protocol Complete. Trading Resumed."*, dispatched together with a Notification Center push (`NC-RISK-04`, `INFO`) — **both SIM and LIVE**.
---
### 6. Alternative Flows
- **Alt-1 — No user breaches either check.**
- Context: every scanned user's `Total_Equity_Loss` and position size stay within limits at T-1min.
- Step 4/5 evaluate to no action for all users; the flow-level "Protocol Active" alert still fires (it is unconditional, not per-user), but `actions: []` in the endpoint output. This is the expected common case for a moderate-impact event that still cleared Filter 1/2.
- **Alt-2 — A user breaches the Universal Drawdown check on one asset class while holding compliant positions on another.**
- Context: a user with both Futures and Forex exposure breaches the 70% drawdown threshold via their Futures book alone.
- Per [BR_6.2.1.4](#BR_6.2.1.4), the Universal Drawdown check is evaluated **per user, not per asset class** — `FLATTEN_ALL` clears the user's entire exposure (both asset classes), not just the breaching one.
---
### 7. Exceptional Flows
- **Exc-1 — A dispatched `TRIM_TO_COMPLIANCE` call from step 5 fails to resolve (gateway rejection, timeout).**
- An automatic retry mechanism handles gateway rejections and timeouts at the dispatch layer — this UC does not describe that retry flow in detail. Source: User instruction, 2026-09-10.
- **Exc-2 — Finnhub's technical API schema (endpoint/auth/payload) has not been provided by the client.**
- Per CHR_67's Open Questions, Finnhub is confirmed as the provider but its API integration details are not yet available. This UC documents the confirmed *business* logic (provider name, cron-poll architecture, Filter 1/2 breakdown, enforcement math); the ingestion-layer technical contract (poll endpoint, auth, payload schema) is tracked as a follow-up QnA item, not blocking this UC's enforcement-side content.
---
### 8. Business Rules
<a id="BR_6.2.1.1"></a>
#### BR_6.2.1.1: Trigger architecture — Finnhub, cron-poll (not webhook)
Flow 23's trigger source is **Finnhub**, replacing the RFQ V7 / Zapier Integration V7.pdf baseline's illustrative placeholder example ("e.g. FXStreet").
Finnhub does **not** push webhooks to this system. Instead, the system actively calls Finnhub's news API on a **scheduled cron job**, polling continuously at a fixed interval, so the latest news events are always available regardless of whether Finnhub supports (or the client has configured) an outbound webhook. Each poll cycle's results are run through Filter 1/Filter 2 ([BR_6.2.1.2](#BR_6.2.1.2)) before being persisted and scheduled onto the T-30/T-10/T-1/T+1 timeline. This replaces the previous Option A/Option B webhook-architecture assumption (`Zapier Integration V7.pdf` §7.1) — that assumption is resolved and removed; there is no webhook signature/token validation step in this UC's trigger path because there is no inbound webhook.
(Source: `Zapier Integration V7.pdf` §Flow 23, lines 2206-2208; [CHR_67](/References/CR/2026-08-28_CHR67_finnhub-replaces-fxstreet/CR_summary.md); cron-poll architecture — User instruction, 2026-09-10)
---
<a id="BR_6.2.1.2"></a>
#### BR_6.2.1.2: Filtering and currency-relevance mapping — full detail
Every event returned by a cron poll cycle ([BR_6.2.1.1](#BR_6.2.1.1)) runs through two filters, in order, before it is persisted and scheduled onto the T-30/T-10/T-1/T+1 timeline:
**Filter 1 — Impact level.**
IF Event.Impact_Level != "High": Discard event (no further processing)
Only high-impact events proceed to Filter 2. Medium/low-impact events are dropped at this step.
**Filter 2 — Currency relevance.** Relevance is evaluated differently per asset class:
- **Futures.** All whitelisted Futures instruments are USD-domiciled. An event is relevant to every Futures trader whenever:
IF Event.Currency == "USD": Relevant to all Futures traders (auto-relevant, no per-trader lookup needed)
- **Forex.** Relevance is trader-specific and evaluated dynamically against that trader's currently open positions — there is no static whitelist:
FOR each Forex trader's open positions: IF Event.Currency == position.Base_Currency OR Event.Currency == position.Quote_Currency: Relevant to this trader
Example: a trader holding an open `EURUSD` position is flagged relevant for a high-impact event where `Event.Currency == "EUR"` or `Event.Currency == "USD"`, but not for a high-impact `GBP` event unless they also hold a `GBP`-denominated position.
Events that pass both filters are persisted to the news-event store and drive the checkpoints in [BR_6.2.1.3](#BR_6.2.1.3).
(Source: [CHR_67](/References/CR/2026-08-28_CHR67_finnhub-replaces-fxstreet/CR_summary.md), Filter 2 relevance breakdown (client-confirmed); [UC_4.7.1](/docs/BA/UC_4.1-4.17/dashboard_sim/UC_4.7.1/UC_4.7.1_v1.md#UC_4.7.1) `BR_4.7.1.4`, same logic documented from the display side — duplicated here in full per direct instruction rather than cross-referenced, User instruction 2026-09-10)
---
<a id="BR_6.2.1.3"></a>
#### BR_6.2.1.3: T-30/T-10/T-1/T+1 broadcast sequence — Slack & Discord + Notification Center, dispatched together
At each of the four flow-level checkpoints, Flow 23 dispatches **two things at once, from the same event**: a **Global Alert to Slack & Discord**, and a **Dashboard Notification Center push** to every affected trader over the `NOTIFICATION` WebSocket event (per [UC_4.7.1](/docs/BA/UC_4.1-4.17/dashboard_sim/UC_4.7.1/UC_4.7.1_v1.md#UC_4.7.1) `BR_4.7.1.3`'s real-time push mechanism — bell badge and open notification list update immediately, no polling). These are not two independent flows; the Notification Center entry is not a separate re-derivation, it is fired alongside the Slack/Discord alert as part of this same checkpoint dispatch:
| Checkpoint | Slack/Discord copy | Notification Center (`Event_ID`, severity, copy) | Per-user or flow-level? |
| ---------- | ------------------------------------------------ | ------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------- |
| T-30min | "News Warning: [Event] in 30 mins" | `NC-RISK-01`, `WARN`, "News Warning: [Event] in 30 mins" | Flow-level |
| T-10min | "News Warning: [Event] in 10 mins" | `NC-RISK-02`, `WARN`, "News Warning: [Event] in 10 mins" | Flow-level |
| T-1min | "News Protocol Active. Holding Limits Enforced." | `NC-RISK-03`, `CRITICAL`, "News Protocol Active. Holding Limits Enforced." | Flow-level (unconditional — fires regardless of whether any individual user is actually flattened/trimmed) |
| T+1min | "News Protocol Complete. Trading Resumed." | `NC-RISK-04`, `INFO`, "News Protocol Complete. Trading Resumed." | Flow-level |
The T-1min checkpoint additionally triggers the per-user enforcement action ([BR_6.2.1.4](#BR_6.2.1.4)/[BR_6.2.1.5](#BR_6.2.1.5)) and the per-user liquidation email ([BR_6.2.1.8](#BR_6.2.1.8)); neither the Slack/Discord alert text nor the Notification Center copy varies per user — both are flow-level broadcasts.
(Source: `Zapier Integration V7.pdf` §Flow 23, lines 2214-2223, 2239; [UC_4.7.1](/docs/BA/UC_4.1-4.17/dashboard_sim/UC_4.7.1/UC_4.7.1_v1.md#UC_4.7.1) `BR_4.7.1.1` (`NC-RISK-01`–`04` event definitions) and `BR_4.7.1.3` (WebSocket push mechanism); simultaneous dual-channel dispatch — User instruction, 2026-09-10)
---
<a id="BR_6.2.1.4"></a>
#### BR_6.2.1.4: Universal Drawdown check — canonical formula, same gate as UC_6.1.2's T-2min Drawdown Safety Gate
At T-1min, before any asset-specific size-cap check, the endpoint evaluates **every user** (Futures and Forex alike) against the **same formula** as [UC_6.1.2](/docs/BA/UC_6.1-6.3/UC_6.1.2/UC_6.1.2_v1.md#UC_6.1.2)'s Universal Drawdown Safety Gate ([BR_6.1.2.2](/docs/BA/UC_6.1-6.3/UC_6.1.2/UC_6.1.2_v1.md#BR_6.1.2.2)):
Total_Equity_Loss = Account_Starting_Equity − Current_Account_Equity
IF Total_Equity_Loss ≥ Market_Loss_When_Stopped × swap_risk_threshold: Action: FLATTEN_ALL
`Account_Starting_Equity` is the account's equity fixed at the start of the trader's current challenge/level (A-25) — not reset daily. `Total_Equity_Loss` is therefore **cumulative loss since challenge/level start**, not the instantaneous unrealized P&L of currently-open positions. `Market_Loss_When_Stopped` is looked up from Table A (Forex) or Table B (Futures) — the same absolute stop-loss threshold value [UC_6.1.2](/docs/BA/UC_6.1-6.3/UC_6.1.2/UC_6.1.2_v1.md#UC_6.1.2) calls `Stop_Loss_Threshold` (same column, two documents' naming). `swap_risk_threshold` (0.70) is the same 70% ratio used there. The two gates are the **same check**, evaluated at different checkpoints: [UC_6.1.2](/docs/BA/UC_6.1-6.3/UC_6.1.2/UC_6.1.2_v1.md#UC_6.1.2) runs it on a fixed overnight schedule (T-2min); this UC runs it on-demand at T-1min, triggered by a qualifying news event. They do not supersede one another — either can independently flatten the same account at its own checkpoint.
> ⚠️ **Change from the original Open_PnL formulation.** This BR previously tested instantaneous `Open_PnL` against `-(Market_Loss_When_Stopped × swap_risk_threshold)`. Per user instruction (BA session), this is corrected to the same `Total_Equity_Loss` (cumulative, since challenge/level start) formula [UC_6.1.2](/docs/BA/UC_6.1-6.3/UC_6.1.2/UC_6.1.2_v1.md#UC_6.1.2)'s Gate 1 (T-2min) uses, so that the T-1min and T-2min drawdown gates are the identical check run at two different times, not two different metrics that happen to share a 70% ratio.
(Source: `RFQ_ Stack Trading Prop Tech V7.pdf` §Risk Enforcement Endpoints — "Enforce News Event", lines 1628-1639; `Zapier Integration V7.pdf` §Flow 23, lines 2224-2230 (flow-level paraphrase); formula corrected to match [UC_6.1.2](/docs/BA/UC_6.1-6.3/UC_6.1.2/UC_6.1.2_v1.md#UC_6.1.2) `BR_6.1.2.2` — user instruction, BA session, 2026-11-05)
---
<a id="BR_6.2.1.5"></a>
#### BR_6.2.1.5: Asset-specific size caps — Forex notional (news-relevant positions only) / Futures ES-Equivalent contract count
For users who pass the Universal Drawdown check ([BR_6.2.1.4](#BR_6.2.1.4)), the endpoint applies an asset-specific size cap:
- **Forex:** `Allowed = Max_Forex_Notional (Table A) × cap_percent`. `IF Current_Notional > Allowed: TRIM_TO_COMPLIANCE, Target_Limit = Allowed`. `Current_Notional` is scoped to only the open Forex positions Filter 2 ([BR_6.2.1.2](#BR_6.2.1.2)) flagged as relevant to the triggering event (`Event.Currency == position.Base_Currency OR position.Quote_Currency`) — not the account's entire open Forex book. A position in an unrelated currency pair that happens to also be open is excluded from this sum and is not acted on by this event's enforcement pass, even though it stays open. Each relevant position's notional uses the same 3-case `Position_Notional_Value` formula as [UC_6.1.3](/docs/BA/UC_6.1-6.3/UC_6.1.3/UC_6.1.3_v1.md#UC_6.1.3) `BR_6.1.3.3` (quote=USD / base=USD / cross-pair via `FX_Conversion_Rate`), summed across those relevant positions only.
- **Futures:** `Final_Allowed_ES_Equiv = Floor(Max_Contracts_ES_Equiv (Table B) × cap_percent)`. `IF Open_Contracts_ES_Equiv > Final_Allowed_ES_Equiv: TRIM_TO_COMPLIANCE, Target_Limit = Final_Allowed_ES_Equiv`. Both sides of this comparison are expressed in **ES-Equivalent units**, never raw contract counts: `Max_Contracts_ES_Equiv` is the account's level/title-based ceiling from Table B (Appendix B), already in ES-Equivalent units; `Open_Contracts_ES_Equiv` is the trader's open Futures book converted the same way [UC_6.1.3](/docs/BA/UC_6.1-6.3/UC_6.1.3/UC_6.1.3_v1.md#UC_6.1.3) step 1 computes `Total_Portfolio_ES_Equiv` — `Σ (Raw_Contract_Count_symbol × ES_Equivalent_Weight_symbol)`, using the same **Appendix C — Futures Relative Risk Helper Table** that UC defines in `BR_6.1.3.1`. Comparing raw contract counts directly against a raw `Max_Contracts` ceiling would treat a Micro contract and a full-size contract as equally "one contract," which they are not — hence the ES-Equivalent normalization on both sides.
`cap_percent` (0.25) is the **same shared Table C variable** established by [UC_6.1.2](/docs/BA/UC_6.1-6.3/UC_6.1.2/UC_6.1.2_v1.md#UC_6.1.2) `BR_6.1.2.5`/A-26 — one config value reused across Futures Required Margin, Forex exposure, and News Events, not three independent 25% constants. The `TRIM_TO_COMPLIANCE` call itself (sort algorithm, event-driven fill confirmation, failsafe timeout) is [UC_6.1.3](/docs/BA/UC_6.1-6.3/UC_6.1.3/UC_6.1.3_v1.md#UC_6.1.3)'s exclusive scope — this UC only computes `Target_Limit` and dispatches.
(Source: `RFQ_ Stack Trading Prop Tech V7.pdf` §Risk Enforcement Endpoints — "Enforce News Event", lines 1640-1656; `Zapier Integration V7.pdf` §Flow 23, lines 2231-2233; [UC_6.1.2](/docs/BA/UC_6.1-6.3/UC_6.1.2/UC_6.1.2_v1.md#UC_6.1.2) `BR_6.1.2.5`, A-26; Forex news-relevant-only scoping + Futures ES-Equivalent comparison — user instruction, 2026-10-27, aligned to [UC_6.1.3](/docs/BA/UC_6.1-6.3/UC_6.1.3/UC_6.1.3_v1.md#UC_6.1.3) `BR_6.1.3.1`'s ES-Equivalent model)
---
<a id="BR_6.2.1.6"></a>
#### BR_6.2.1.6: Concurrency — parallel batch execution, non-blocking
All `FLATTEN_ALL`/`TRIM_TO_COMPLIANCE` actions dispatched from a single `/enforce-news-event` invocation execute in **parallel, non-blocking batches** for millisecond latency. One user's action must not be serialized behind another's — this mirrors the isolation-per-account principle already stated for [UC_6.1.2](/docs/BA/UC_6.1-6.3/UC_6.1.2/UC_6.1.2_v1.md#UC_6.1.2)'s NFRs ("Isolation per asset class"), extended here to isolation per user across a potentially large batch of simultaneously-affected accounts.
(Source: `Zapier Integration V7.pdf` §Flow 23, lines 2234-2235 — "Executes these commands in parallel batches (non-blocking) for millisecond latency")
---
<a id="BR_6.2.1.7"></a>
#### BR_6.2.1.7: Endpoint output and Slack summary — naming variance reconciled, per-asset-class breakdown
The canonical endpoint-level output shape (`RFQ_ Stack Trading Prop Tech V7.pdf`) is:
```json
{ "scanned": int, "actions": [...] }Zapier Integration V7.pdf's flow-level description paraphrases the same response as { "traders_processed": X, "liquidations_triggered": Y }. This UC treats the endpoint-level { "scanned", "actions" } shape as canonical (same precision rationale as BR_6.2.1.4); traders_processed/liquidations_triggered are read as descriptive paraphrases of scanned and a count derived from actions, not a second, conflicting field set.
Slack summary — one block per asset class. Since the Universal Drawdown check (BR_6.2.1.4) and size caps (BR_6.2.1.5) run separately for Futures and Forex, the #risk-ops summary reports traders_processed/liquidations_triggered once per asset class, not one pooled total:
[News event] Futures / Forex Liquidation Execution Summary
Future Summary:
Traders Processed: {traders_processed} traders
Liquidations Triggered: {liquidations_triggered} traders
Forex Summary:
Traders Processed: {traders_processed} traders
Liquidations Triggered: {liquidations_triggered} traders| Field | Meaning |
|---|---|
traders_processed (X) | Count of LIVE traders in that asset class the endpoint scanned this run — equivalent to scanned, scoped to Futures or Forex. Every LIVE trader evaluated by the Universal Drawdown check this cycle, regardless of outcome. |
liquidations_triggered (Y) | Count of traders in that asset class against whom FLATTEN_ALL or TRIM_TO_COMPLIANCE was actually dispatched — the Futures- or Forex-scoped slice of actions. Always ≤ traders_processed; 0 when no trader in that asset class breached either check this cycle (Alt-1). |
This summary is distinct from the T-30/T-10/T-1/T+1 Global Alerts (BR_6.2.1.3), which go to the Global Alert channels (Slack & Discord) rather than #risk-ops specifically and carry no numeric breakdown.
(Source: RFQ_ Stack Trading Prop Tech V7.pdf §Risk Enforcement Endpoints — "Enforce News Event", Output column; Zapier Integration V7.pdf §Flow 23, lines 2236-2237; per-asset-class Slack template — user instruction, BA session, 2026-11-05)
BR_6.2.1.8: Per-user liquidation email — SES-18 / News_Liquidation_Alert
Whenever step 4 or step 5 of the Basic Flow dispatches an action against a specific user (FLATTEN_ALL or TRIM_TO_COMPLIANCE), the system sends that trader a liquidation email using:
| Field | Value |
|---|---|
| Email ID | SES-18 |
| Template Key | News_Liquidation_Alert |
| Trigger | Automated position flattening/trimming triggered during a high-impact economic event |
| Recipient | The affected trader |
| Required content | Urgent notice detailing the automated position action, the triggering event name, and its timestamp |
This is a per-user notification distinct from the flow-level Slack/Discord + Notification Center broadcasts in BR_6.2.1.3 — it only fires for a user who was actually acted on, not for every trader who received the T-1min "Protocol Active" alert.
(Source: list_email.md SES-18; User instruction, 2026-09-10)
BR_6.2.1.9: T-1min enforcement calculation applies to LIVE accounts only — broadcast sequence remains SIM + LIVE
This UC's two halves have different account-type scope, and the two must not be conflated:
- T-30/T-10/T-1/T+1 broadcast sequence (BR_6.2.1.3) — both SIM and LIVE. The Global Alert (Slack/Discord) + Notification Center push at every checkpoint is informational and carries no account-level action by itself. It is dispatched to every affected trader regardless of account type — SIM and LIVE traders both see the T-30min/T-10min warnings, the T-1min "Protocol Active" notice, and the T+1min "Protocol Complete" notice.
- T-1min
/enforce-news-eventcalculation — LIVE accounts only. The Universal Drawdown check (BR_6.2.1.4) and the asset-specific size-cap check (BR_6.2.1.5) that this endpoint runs at T-1min, and theFLATTEN_ALL/TRIM_TO_COMPLIANCEactions either check can dispatch, evaluate and act on LIVE accounts only. A SIM account'sTotal_Equity_Lossis not checked againstMarket_Loss_When_Stopped × swap_risk_threshold, its Forex notional/Futures contract count is not checked against the asset-specific cap, and it is never flattened or trimmed by this UC. Thescanned/actionscounts in the endpoint output (BR_6.2.1.7) and the#risk-opsSlack summary derived from them reflect LIVE accounts only. - Per-user liquidation email (BR_6.2.1.8) — LIVE accounts only, as a direct consequence: since only a LIVE account can be the target of a
FLATTEN_ALL/TRIM_TO_COMPLIANCEdispatch here,SES-18/News_Liquidation_Alertonly ever fires for a LIVE trader.
This mirrors the T-30/T-10/T-1/T+1 warning sequence being a shared, account-type-agnostic broadcast layer, while the actual position-affecting enforcement underneath it is LIVE-specific — the same split pattern already used elsewhere in the SRS between a universal notification layer and an environment-specific action layer.
(Source: user instruction, 2026-10-26 — "UC này chỉ áp dụng cho tài khoản live không áp dụng cho Sim ở logic tính toán mốc T-1.")
9. Update History
| Date | Version | Section | Change From | Change To | Source |
|---|---|---|---|---|---|
| 2026-09-06 | v1 | All (new) | UC_6.2.1 not yet written | Initial SRS for UC_6.2.1, covering Flow 23's Global Alert broadcast sequence and /enforce-news-event enforcement logic (Universal P&L check + Futures/Forex size caps), with Finnhub provider and Filter 2 breakdown applied per CHR_67 and cross-referenced (not duplicated) from UC_4.7.1 | RFQ_ Stack Trading Prop Tech V7.pdf lines 1628-1656; Zapier Integration V7.pdf lines 2206-2239, 2747-2823; CHR_67; UC_4.7.1 BR_4.7.1.4 |
| 2026-09-10 | v1 | §9-10, Trigger, BR_6.2.1.1-3, Exc-1-2 removed (old) | (1) NFRs/Acceptance Criteria sections; (2) Trigger described Finnhub as webhook source with an open Option A/Option B architecture assumption in BR_6.2.1.1; (3) BR_6.2.1.2 cross-referenced UC_4.7.1 instead of stating filter logic; (4) BR_6.2.1.3 described Global Alert as Slack/Discord-only, explicitly not the Notification Center; (5) Exc-1 (missing Market_Loss_When_Stopped) and old Exc-2 (TRIM_TO_COMPLIANCE gateway rejection/timeout flow) described in full | (1) Both sections removed, Update History renumbered to §9; (2) Trigger + BR_6.2.1.1 rewritten — Finnhub is now polled via a scheduled cron job (no webhook), assumption removed; (3) BR_6.2.1.2 rewritten with full Filter 1/Filter 2 Futures-Forex logic duplicated inline; (4) BR_6.2.1.3 rewritten — every Slack/Discord Global Alert now dispatches together with a Notification Center push (NC-RISK-01–04) over the same checkpoint; (5) old Exc-1 deleted entirely (will not occur); old Exc-2's flow description removed and replaced with a one-line note that an automatic retry mechanism handles gateway rejection/timeout (renumbered Exc-1); old Exc-3 renumbered to Exc-2 unchanged; (6) added new BR_6.2.1.8 — per-user News_Liquidation_Alert email (SES-18) sent on FLATTEN_ALL/TRIM_TO_COMPLIANCE, referenced from Basic Flow step 7 and Post-conditions | User instruction, 2026-09-10 |
| 2026-09-17 | v1 | §5 Basic Flow (steps 0, 3, 4, 5, 6, 7, 8) | Filter/formula steps (Filter 1/2, the P&L check, the Forex/Futures size caps) and the concurrency/email/output steps stated their logic and then pointed to §8 (See [BR_6.2.1.1]/[.2]/[.4]/[.5]/[.6]/[.7]/[.8]) for what each field/variable means or what the rule actually does | Every filter and formula step now defines each of its own fields/variables inline, directly beneath the logic block; the concurrency, per-user email, and endpoint-output steps now state their full behavior in place, with no See [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-26 | v1 | Intro blockquote (new SIM/LIVE note); Overview (Description); §3 Pre-conditions (P-2/P-3/P-4); §4 Post-conditions (all T-1min entries); §5 Basic Flow (steps 1-4, 8, 9); §8 (new BR_6.2.1.9) | This UC never explicitly stated whether its T-30/T-10/T-1/T+1 broadcasts and T-1min /enforce-news-event calculation apply to SIM accounts, LIVE accounts, or both | Added an explicit scope split, confirmed by the client/BA: the T-30/T-10/T-1/T+1 broadcast sequence (Global Alert + Notification Center) fires for both SIM and LIVE traders — it is informational only. The T-1min /enforce-news-event calculation itself — the Universal P&L check (BR_6.2.1.4), the asset-specific size-cap check (BR_6.2.1.5), and the resulting FLATTEN_ALL/TRIM_TO_COMPLIANCE dispatch and per-user SES-18 email (BR_6.2.1.8) — applies to LIVE accounts only; SIM accounts are excluded from the evaluation scan entirely, not merely exempted from the resulting action. New BR_6.2.1.9 documents this split in full. Intro blockquote, Overview Description, §3 P-2/P-3/P-4, §4's T-1min post-condition entries, and §5 Basic Flow steps 1-4/8/9 updated to flag SIM+LIVE vs. LIVE-only at each relevant point | User instruction 2026-10-26 — "UC này chỉ áp dụng cho tài khoản live không áp dụng cho Sim ở logic tính toán mốc T-1." |
| 2026-10-26 | v1 | §5 Basic Flow (step 4 — Gate 1 worked examples added; step 5 — Gate 2 worked examples added) | Step 4 (Universal P&L check, Gate 1) and step 5 (asset-specific size caps, Gate 2) stated their formulas with no worked numeric example for either asset class | Added a Futures and a Forex worked example to each gate's calculation step. Step 4: Futures (Market_Loss_When_Stopped = $5,000 Table B, Open_PnL = -$2,000 → check passes) and Forex (Market_Loss_When_Stopped = $10,000 Table A, Open_PnL = -$8,200 → check breaches, FLATTEN_ALL), showing both outcome paths. Step 5: Forex (Max_Forex_Notional = $200,000 Table A, cap_percent = 25% → Allowed = $50,000; Current_Notional = $62,000 → breach, TRIM_TO_COMPLIANCE Target_Limit = $50,000) and Futures (Max_Contracts = 8 Table B → Final_Allowed = Floor(8 × 0.25) = 2; Open_Contracts = 5 → breach, TRIM_TO_COMPLIANCE Target_Limit = 2) | User instruction 2026-10-26 — "Hãy update cho tôi mô tả ở các basic flow phần tính toán ở gate 1 và gate 2 sẽ đều có ví dụ cụ thể theo từng asset class future và forex." |
| 2026-10-27 | v1 | Overview (Zapier Table, Description); §3 P-3; §4 Post-conditions (size-cap breached entry); §5 Basic Flow step 5 (Gate 2 — formulas + worked examples rewritten); §8 BR_6.2.1.5 | Step 5's Forex leg checked Current_Notional as if it summed the trader's entire open Forex book, with no rule excluding positions unrelated to the triggering news event; its Futures leg compared a raw Open_Contracts count directly against a raw Max_Contracts (Table B) ceiling, with no ES-Equivalent conversion — inconsistent with UC_6.1.3's Appendix C ES-Equivalent model that this same TRIM_TO_COMPLIANCE dispatch feeds into | Forex: Current_Notional is now explicitly scoped to only the open Forex positions Filter 2 (BR_6.2.1.2) flagged as relevant to the triggering event (shared currency leg) — a position in an unrelated pair is excluded from the sum even though it stays open; restated the 3-case Position_Notional_Value formula (quote=USD / base=USD / cross-pair via FX_Conversion_Rate) inline, same formula as UC_6.1.3 BR_6.1.3.3. Futures: both sides of the cap check are now expressed in ES-Equivalent units — Max_Contracts_ES_Equiv (Table B, Appendix B, already ES-Equivalent) vs. Open_Contracts_ES_Equiv (Σ Raw_Contract_Count_symbol × ES_Equivalent_Weight_symbol, using UC_6.1.3's Appendix C), replacing the raw-contract-count comparison; worked examples updated accordingly (Forex: EURUSD news-relevant vs. AUDNZD excluded; Futures: 8 MES → 0.8 ES-Equiv vs. 0.2 ES-Equiv cap) | User instruction 2026-10-27 — "Đối với Forex, current notional ở đây chỉ được tính của các position liên quan đến tin tức... Đối với future, hãy mô tả rõ rằng open contracts ở đây là open contract được quy đổi theo cùng 1 đơn vị ES và Max_contracts ở final_allowed cũng được quy đổi ra đơn vị ES để so sánh" |
| 2026-11-05 | v1.1 | Overview (Use Case, Description); Intro blockquote; §3 P-2; §4 Post-conditions (T-1min entries); §5 Basic Flow step 4 (renamed), step 8 (Slack template added); §6 Alt-1/Alt-2; §8 BR_6.2.1.4 (formula replaced), BR_6.2.1.5/BR_6.2.1.7 (renamed/expanded), BR_6.2.1.9 | (1) Step 4/BR_6.2.1.4's "Universal P&L check" tested instantaneous Open_PnL against -(Market_Loss_When_Stopped × swap_risk_threshold) — a different metric from UC_6.1.2's T-2min Drawdown Gate despite sharing the same 70% ratio. (2) Step 8/BR_6.2.1.7's Slack summary described traders_processed/liquidations_triggered as one pooled pair of figures with no stated template text and no per-asset-class breakdown. | (1) Gate 1 formula corrected to match UC_6.1.2's T-2min Gate 1 exactly: renamed "Universal P&L check" → "Universal Drawdown check" throughout (Overview, blockquote, Post-conditions, Alt-1/Alt-2, BR_6.2.1.4, BR_6.2.1.5, BR_6.2.1.9); formula changed from Open_PnL < -(Market_Loss_When_Stopped × swap_risk_threshold) to Total_Equity_Loss = Account_Starting_Equity − Current_Account_Equity; IF Total_Equity_Loss ≥ Market_Loss_When_Stopped × swap_risk_threshold → FLATTEN_ALL — the same cumulative-loss-since-challenge-start formula as UC_6.1.2 BR_6.1.2.2, now explicitly the same gate run at a different checkpoint (T-1min here vs. T-2min there), not a separate metric; worked examples recomputed using Account_Starting_Equity/Current_Account_Equity instead of Open_PnL. (2) Slack summary template documented in full, with a per-asset-class (Futures/Forex) breakdown: added the exact [News event] Futures / Forex Liquidation Execution Summary template to step 8 and BR_6.2.1.7, and defined traders_processed (LIVE traders scanned for that asset class) and liquidations_triggered (subset actually flattened/trimmed for that asset class, always ≤ traders_processed) | User instruction, BA session, 2026-11-05 — "Hãy update mô tả cho tôi template của Slack summary... update thêm cho tôi công thức tính toán ở gate 1 của flow 23 không phải là open PnL mà đúng công thức giống như gate 1 mốc T-2 là check total loss với ngưỡng 70% stop_loss" |