StackTrading Docs

SRS: UC_4.17.1 — Settings: Market Data Management (LIVE)

UC_4.17.1: Settings — Market Data Management (LIVE)

FieldValue
BA in ChargeAnh Hoang
Date Created2026-09-04
Versionv2
Document ReferencesBroadcast, Settings_Market Data.docxSettings - Market Data management §1.0 UI/UX, §2.1 Payment Methods, §2.2 Active Subscriptions) · QnA from clients — QnA_STAGE2_SETTINGS_CAREER_VIRAL.md §4 Market Data Management ([MDM-DEF-06], [MDM-DEF-08], [MDM-BIZ-01][MDM-BIZ-20], [MDM-UI-01][MDM-UI-09], [MDM-ZAPF-01][MDM-ZAPF-06], [MDM-ZAPT-01], [MDM-EP-01]) · Zapier Integration V7.pdf (§Flow 12 — The "Zombie" Protocol, §Flow 22 — Monthly Data Fee Billing, §Flow 39, §Table C) · RFQ_ Website and Dashboard Implementation V7.pdf (§Part C — Market Data Management) · RFQ_ Stack Trading Prop Tech V7.pdf (§Market data endpoints, §Process Payment Webhook) · CR-20260812-008 · CR-20260727-005 · CR-20260818-003 · CR-20260818-004 · Wireframe References/Wireframe/Stage 2/Settings/Market Data Management/

Document References

#SourceSections used
1Broadcast, Settings_Market Data.docx (Adrian Stack, 2026-08-10)§1.0 — modal subheader changed to Monthly Subscription, primary button changed to Subscribe, disabled Purchased button changed to an active Unsubscribe. §2.1 — the four card-management endpoints. §2.2 — Get Active Subscriptions, Cancel Subscription (returns access_valid_until)
2QnA from clients — QnA_STAGE2_SETTINGS_CAREER_VIRAL.md §4Every confirmed business rule for this screen: calendar-month billing cycle, who pays for CME by level, one payment method for all feeds, mid-cycle unsubscribe, card expiry, device-conditional wallets, the two billing paths (Path A / Path B), the R|Trader Pro signing reminder modal ([MDM-UI-09]) and the removal of the blocking rule on add-on purchases ([MDM-BIZ-20]), split CTAs per payment mechanism ([MDM-UI-07]), shared sub-text ([MDM-UI-06]), APM refunds via outbound push ([MDM-BIZ-19]), the single Resubscribe label ([MDM-UI-08]), Table C prices
3Zapier Integration V7.pdf§Flow 12 — The "Zombie" Protocol: daily cron at 02:00 AM Central, last_trade_date < (Today − 30) → disable data feeds via broker API → email → reactivation link. §Flow 22 — Monthly Data Fee Billing: invoice generation, vault charge, End of Month Hard Check. §Flow 39 — resend R|Trader Pro instructions. §Table C — the four price variables
4RFQ_ Website and Dashboard Implementation V7.pdf§Part C — Data Feed Status badge, POST /toggle-market-data, GET /market-data-products (auto-filters products the user already owns), POST /execute-checkout with product_id="MARKET_DATA"
5RFQ_ Stack Trading Prop Tech V7.pdf§Market data endpoints · §Process Payment Webhook (writes market_data_paid_until) · §GET /financial/calculate-data-refund
6CR-20260812-008Process Payment Webhook parses addon_ids → writes market_data_flags, in the same transaction as setup_status='Complete' + market_data_billable=True
7CR-20260727-005Exchange-agreement reminder banner, shown on the Command tab. UC_4.6.1 already ruled that this banner belongs to the Market Data Management tab, not to Connections & Credentials
8CR-20260818-003Sixth Notification Center category — Billing & Subscriptions
9CR-20260818-004The Alternative Payment Method (APM) monthly prepay path for traders without a card
10list_email.md — Email Template RegistrySES-30 Zombie_Account_Pause (Flow 12) · SES-31 Invoice_APM_email (Flow 22 Path A) · SES-16 Urgent_Data_Payment_Required (Flow 22 Path B) · SES-17 Data_Feed_Downgraded (Flow 22 Hard Check). Full copy lives in the registry; this UC does not repeat it
11Wireframe References/Wireframe/Stage 2/Settings/Market Data Management/24 frames — main tab (3 variants), Subscribe modal (4 states), Change Payment Method / Change Payment Card / Add Payment Method, Unsubscribe, Subscription Confirmed, Subscription Cancelled, Payment Failed, Card In Use, Switch to Manual Billing, and the Action Required: Exchange Agreements Pending modal (Phần ngoài/-.png — shown on the Command tab)
12slack_channel_usage.md — Slack Channel Usage Map§14 — the INVOICE_PAYMENT_FAILED Ops alert and its channel (#ops-general). Ref: BR_4.17.1.20
13UC_4.15.2 — Hard Breach: Level Stop (LIVE)§5 Basic Flow Step 2 — Refund Check (Market Data). That step owns the whole market-data refund mechanism, including the branch for gateways that cannot reverse a payment automatically. This UC references it and does not restate it — Ref: BR_4.17.1.17

1. Overview

FieldContent
IDUC_4.17.1
Use CaseSettings — Market Data Management
DescriptionA tab inside the Account (Settings) screen where a LIVE trader can see the status of each exchange data feed (CME Level 2, CBOT, NYMEX, COMEX), buy extra feeds, cancel feeds, switch paused feeds back on, and manage the one payment method that funds all of them. The tab is also where the trader sees the effect of two background jobs: Flow 12 (switches feeds off after 30 days without trading) and Flow 22 (collects the monthly data fee).This UC also owns the exchange-agreement reminder modal and banner — both shown on the Command tab at every login while the trader has not signed with Rithmic. They only remind; they do not block the trader from buying add-ons or moving around the dashboard (Ref: §6.11, §9.6).
ActorLIVE trader (Futures)
Zapier FlowFlow 12 — The "Zombie" Protocol · Flow 22 — Monthly Data Fee Billing (C-Corp) · Flow 39 — Resend R|Trader Pro Instructions
Zapier TableTable C (Global_Variables) — Price_Data_CME, Price_Data_CBOT, Price_Data_NYMEX, Price_Data_COMEX · Payment_Method_Config (gateways by country)
3rd PartyRithmic (enable/disable feeds, exchange-agreement signature status) · NMI (Customer Vault, recurring charge) · T365 / Dusupay / PayRetailers (Alternative Payment Methods) · AWS SES + Klaviyo (email)

Wireframe: References/Wireframe/Stage 2/Settings/Market Data Management/[BA Wireframe] Stack Trading Design/Account (Market Data Management).png and the other frames in the same folder.

2. Trigger

  • Trader: opens Settings → clicks the Market Data Management tab.
  • Trader: clicks the CTA in a Flow 22 dashboard notification or email — both land on this tab (Ref: BR_4.17.1.20).
  • Trader logs in while the Rithmic exchange agreement is still unsigned → the Action Required: Exchange Agreements Pending modal opens by itself on the Command tab (Ref: §6.11).
  • System — Flow 12: daily cron at 02:00 AM Central scans for traders who have not traded in 30 days (Ref: §6.9).
  • System — Flow 22: monthly cron at EOM−7 (Path A) or EOM−3 (Path B), plus the End of Month Hard Check on the last day of the month (Ref: §6.10).

3. Pre-conditions

  • The trader is logged in and is in the LIVE environment (Ref: BR_4.17.1.1).
  • The trader's asset class is Futures. Forex traders do not get this tab — their feeds come from MT5 / TraderEvolution, which carry no separate exchange data fee.
  • users.status is not Terminated (hard breach or resignation) — Ref: BR_4.17.1.1.
  • Table C holds all four price variables. Without them GET /market-data-products cannot return a price and the Subscribe modal cannot open (Ref: BR_4.17.1.2).

4. Post-conditions

  • The trader sees the true state of all four feeds, reconciled between the database and Rithmic.
  • After a successful Subscribe: the new feed is added to market_data_flags, market_data_paid_until is set to the last day of the current calendar month, and the feed is provisioned on Rithmic.
  • After an Unsubscribe: the feed stays active until market_data_paid_until, then switches off and drops out of Flow 22's next invoice run.
  • After a payment-method change: is_default moves to the new card and every later Flow 22 charge uses it.

5. Basic Flow — Viewing the data feed list

  1. The trader opens Settings → clicks the Market Data Management tab.
  2. The frontend calls three endpoints in parallel:
    • GET /market-data-status[{feed_name, status, paid_until_date}] — entitlement state held in the database.
    • GET /check-market-data-status{db_entitlements, rithmic_status: {CME, CBOT, NYMEX, COMEX}} — signature status read live from the Rithmic API. The frontend must never infer signature status from the database (Ref: BR_4.17.1.14).
    • GET /market-data-products → the price of each feed, read from Table C.
  3. The frontend calls Get Saved Cards to list saved cards and identify the is_default one, and reads customer_vault_id to decide whether the trader is on Path A or Path B (Ref: BR_4.17.1.10).
  4. The frontend renders:
    • The billing bar at the top of the panel — Path B shows All feeds billed to [brand] Ending in [last4]; Path A shows All feeds billed to Alternative Payment Method. Both carry a Change link.
    • Four feed cards in a fixed order: CME Level 2CBOTNYMEXCOMEX.
    • Each card: feed name + status badge + info chip (if any) + description line + action button. Full matrices in BR_4.17.1.3, BR_4.17.1.4, BR_4.17.1.5.
  5. If the trader has not signed the exchange agreement, the Command tab shows the reminder banner (Ref: BR_4.17.1.15).

6. Alternative Flow

6.1 Subscribe — buying a new feed

  1. The trader clicks Subscribe on a feed they do not own yet.
  2. The Subscribe to Market Data modal opens. There is no signature gate at this step — a trader who has not signed the exchange agreement can still buy and pay; they simply will not see data flowing until they sign (Ref: BR_4.17.1.14). The modal shows: the product line ([FEED] + sub-text Full depth-of-book + price), a Tax ([state]) line, a Total line, the payment selector, and the disclosure block (Ref: §9.2).
  3. The trader picks one of two payment mechanisms. Each has its own CTA — they are never merged into one generic button (Ref: BR_4.17.1.24):
    • Charged Automatically — use a saved card. This is auto-pull: the system charges the vault token on schedule. CTA: Subscribe via Credit Card. If no card is saved, the radio also reads (No payment card yet) and offers an Add New link.
    • Alternative Payment Method — pick one APM tile (Pix / UPI / Bank Transfer…). This is manual push: the trader pays each time themselves. CTA: Pay via APM. The tile list is rendered dynamically from GET /system/status based on the trader's country (Ref: BR_4.17.1.13).
  4. The trader clicks the CTA → the frontend calls POST /execute-checkout with {product_id: "MARKET_DATA", addon_ids: [feed_id], payment_method, user_id}.
  5. The backend charges through NMI (card path) or redirects to the APM gateway (APM path).
  6. On success the Process Payment Webhook writes, in one transaction: the new feed into market_data_flags, market_data_paid_until = last day of the current calendar month, and market_data_billable according to level (Ref: BR_4.17.1.6, BR_4.17.1.7). The middleware then calls the Rithmic API to provision the feed.
  7. The frontend shows the Subscription Confirmed modal (Ref: §9.5). Clicking Back to Market Data returns to the tab, where the card is now Active with an Unsubscribe button.

6.2 Unsubscribe — cancelling an active feed

  1. The trader clicks Unsubscribe on an Active feed card. This button never appears on the CME card (Ref: BR_4.17.1.5).
  2. A confirmation modal Unsubscribe from [FEED]? opens, stating that the feed keeps running until the end of the calendar month already paid for, that no refund is issued, and the earliest date they can subscribe again.
  3. The trader clicks Unsubscribe → the frontend calls Cancel Subscription {user_id, product_id}.
  4. The backend looks up the gateway behind that subscription:
    • NMI → tell NMI to terminate the recurring billing profile.
    • APM → set an internal flag that blocks any automatic renewal.
    • Either way → work out the end of the paid cycle, leave the feed active at the broker until that date, and return access_valid_until.
  5. The frontend shows Subscription Cancelled. The card then switches to an Active until [MMM DD] badge with the Subscribe button disabled until the cycle ends (Ref: BR_4.17.1.8).
  6. Flow 22 drops this feed from its next invoice run.

6.3 Resubscribe — a feed paused by Flow 12

Applies when a feed is Inactive with the info chip Paused after 30 days without trading, i.e. status = Inactive_Hold set by Flow 12.

Flow 12 only pauses the data feed after 30 days without trading; it does not cancel the subscription. But data is billed by calendar month (BR_4.17.1.7), so whether the trader pays anything to switch it back on depends on which month they are in when they do it.

Case 1 — Switching back on inside the month already paid for (no charge)

Condition: market_data_paid_until >= TODAY — the paid cycle is still valid.

Why this is free. CME charges a flat fee per User ID, per calendar month. Turning the same User ID off and back on within one month costs nothing extra — the firm can toggle as often as it likes without exceeding that month's cap. That is exactly why Case 1 needs no checkout (Source: QnA_STAGE2_FAILURE_AND_RECOVERY.md FR-62).

  1. The trader clicks Resubscribe.
  2. The frontend calls POST /toggle-market-data {user_id, enable_data: true}.
  3. The middleware calls the Rithmic API to switch the feed back on. No checkout modal, no charge.
  4. A Success toast appears, the card returns to Active, and the Paused after 30 days without trading chip disappears.

Case 2 — Switching back on in a new month (payment required)

Condition: market_data_paid_until < TODAY — the paid cycle has expired and a new calendar month has started.

  1. The trader clicks Resubscribe.
  2. The frontend opens the Subscribe to Market Data modal — the new cycle has not been paid for.
  3. The rest follows §6.1.

Exception — CME for Level 3+ traders

A trader at Level 3 or above switching CME back on always follows Case 1 (free, no checkout) whatever the month, because the firm pays for base CME and the trader never paid for it in the first place (Ref: BR_4.17.1.6).

This exception does not cover:

  • Level 1–2 traders — they pay for CME themselves, so Case 1 / Case 2 applies normally.
  • The CBOT / NYMEX / COMEX add-ons at any level.

Exchange agreement

Switching a feed back on after Flow 12 does not require signing again — Rithmic ties signatures to the User ID, and Flow 12 never hard-deletes the User ID.

6.4 Resubscribe — a feed switched off after a failed payment

Applies when a feed is Inactive with the info chip Suspended on [MMM DD, YYYY] – Payment couldn't be completed, i.e. the feed was downgraded by Flow 22's End of Month Hard Check.

  1. The trader clicks Resubscribe.
  2. The frontend opens the Subscribe to Market Data modal — the new cycle is unpaid.
  3. The rest follows §6.1.
  4. If a broken card caused the failure, the trader should change it first through the Change link on the billing bar or the Change link inside the modal.

6.4a Where Flow 12 and Flow 22 meet — edge cases

The two background jobs run independently but act on the same feed, so a few situations are easy to get wrong:

#SituationCorrect handling
1Bought near month end, then reactivated. Trader buys NYMEX on Mar 30. Flow 22 runs Day 0 (Mar 31) and charges April as well. The feed is later paused by Flow 12 and the trader switches it back on during AprilNo new charge. market_data_paid_until is already Apr 30, so this is Case 1. This is also the first-month double charge that BR_4.17.1.7 warns about in the Subscribe modal — the trader pays twice (March and April) but still only once per month
2A feed is paused by Flow 12 but still within its paid cycle — does Flow 22 keep charging?Yes. Flow 12 does not cancel the subscription, so Flow 22 still raises an invoice and charges for the next cycle. The trader keeps paying even while the feed is off
3A feed paused by Flow 12, then Flow 22 fails to charge at month endThe chip changes from Paused after 30 days without trading to Suspended on [MMM DD, YYYY] – Payment couldn't be completed. Reactivating now follows §6.4payment required
3aBought in the last 3 days of the month (Path B) and the Day 0 charge fails. E.g. bought Aug 29, Day 0 (Aug 31) charges for September and is declinedThe feed is switched off the same day, with no grace period. The trader never received the EOM−3 warning, so they had no chance to fix the card — their first contact about it is the downgrade email SES-17. Ref: §6.10 Day 0 sweep
4A Path A trader buys an add-on in the last 7 days of the month. E.g. pays by APM on Mar 26No Invoice_APM_email goes out for that cycle, because the EOM−7 cron already ran before the purchase. Instead the trader sees the Remaining Extension Period chip and the Extend button on the billing bar and pays for the next month themselves (Ref: §9.1 row 3)
5A Level 3+ trader has CME paused by Flow 12 at the same time as an add-onCME comes back free under the exception in §6.3; the add-on still follows Case 1 / Case 2 depending on market_data_paid_until. The trader may have to pay for the add-on but never for CME
6Trader unsubscribes, the feed expires, and then Flow 12 runsThe feed is already in the not-subscribed state (no badge), so Flow 12 has nothing to switch off. The button is Subscribe, not Resubscribe
7Flow 12 runs while a feed is in the post-unsubscribe grace window (Active until [MMM DD])The feed goes off earlier than access_valid_until. The badge becomes Inactive with the Paused after 30 days without trading chip. The trader can switch it back on under Case 1 (still inside the paid month) for free, but the subscription is still cancelled, so it stops for good at access_valid_until and does not renew
8Flow 12 runs on a feed already switched off by a failed payment (Suspended)Flow 12 has nothing more to switch off. The chip stays Suspended on [MMM DD, YYYY] – Payment couldn't be completed and is not overwritten by Paused after 30 days without trading, because the underlying reason is unpaid money and reactivating still requires payment (§6.4)
9Trader reaches Level 3 mid-billing-cycle — e.g. promoted on Aug 29, after the EOM−3 cron already charged them at the Level 1–2 rateThe amount already charged is not refunded on a tier basis; what the trader paid at Level 1–2 is compensated by the Level 3 reimbursement perk through GET /financial/calculate-data-refund (BR_4.17.1.6). From the next cycle onwards Flow 22 uses the Level 3+ formula and the Covered by Stack Trading · No charge to you chip appears on the CME card
10Trader buys a new feed while an older feed is paused by Flow 12Buying a new feed does not switch the paused ones back on. The new feed is Active; the older ones keep the Paused after 30 days without trading chip until the trader clicks Resubscribe on each of them

6.5 Changing the payment method

  1. The trader clicks the Change link on the tab's billing bar.
  2. The Change Payment Method modal opens (Ref: §9.3) — methods listed on the left, details of the selected one on the right.
  3. The trader picks a different card under Charged Automatically → the right column shows that card's details (brand, last four digits, expiry, billing address, Delete button).
  4. The trader clicks Done → the frontend calls Update Subscription Payment {user_id, subscription_id, new_billing_id} for every active market data subscription and sets the new card as is_default.
  5. The billing bar on the tab updates to the new card.

Changing the payment method is an account-wide action that applies to every feed at once — there is no per-feed payment method (Ref: BR_4.17.1.9).

6.6 Adding a new card

  1. Inside Change Payment Method, the trader clicks Add new payment method.
  2. The right column becomes the add-card form: the wallet button (Apple Pay or Google Pay depending on device — Ref: BR_4.17.1.12), an or divider, then Name on card / Card number / Expiration (MM/YY) / CVC plus the Billing address is the same as the address checkbox.
  3. The trader fills it in and clicks Add Payment Method → the frontend tokenizes the card and calls Add Saved Card {user_id, payment_token}.
  4. NMI stores the card against the trader's customer_vault_id and returns {billing_id, brand, last4, exp_month, exp_year}.
  5. A Payment method added successfully toast appears; the new card shows up in the left list and is pre-selected.
  6. The trader clicks Done to apply the new card to their subscriptions (step 4 of §6.5).

6.7 Deleting a card

  1. The trader selects a card on the left → clicks Delete on the right.
  2. If that card funds at least one market data subscription → the deletion is blocked and the Card In Use modal lists the subscriptions using it (Ref: §9.5, BR_4.17.1.19). The trader can pick Change Payment Method to assign a different card first, or Close.
  3. If the card funds nothing → call Delete Saved Card {user_id, billing_id}; NMI deletes the token permanently and the card disappears from the list.

6.8 Switching from card to Alternative Payment Method

  1. Inside Change Payment Method, the trader selects the Alternative Payment Method radio under You Pay Each Month.
  2. The right column switches to the How It Works block (3 steps) — Ref: §9.3.
  3. The trader clicks Done → the Switch to Manual Billing? warning modal opens, spelling out that they must actively pay the invoice before the end of each month or lose their feeds.
  4. The trader clicks Confirm Switch → the system moves them to Path A: the NMI recurring profile is cancelled and the trader is flagged to receive a manual invoice from Flow 22 at EOM−7.
  5. The billing bar changes to All feeds billed to Alternative Payment Method. The Remaining Extension Period chip and Extend ([n] Feeds) button only appear once the last 7 days of the month begin (Ref: §9.1 row 3).
  6. Clicking Keep Automatic closes the modal and keeps the card.

6.9 Flow 12 — The "Zombie" Protocol (background job)

Purpose: stop paying for data feeds on dormant accounts. This is purely a cost-control tool, not an account-termination flow.

  1. Trigger: daily cron at 02:00 AM Central.
  2. Scan: SELECT * FROM traders WHERE last_trade_date < (Today − 30).
    • The counter uses the raw last_trade_date and does not subtract approved time off. A trader on Flow 13 DTO / hiatus is still caught by Flow 12 (Ref: BR_4.17.1.21).
  3. Batch Push: the database sends a webhook with the list of inactive traders to Zapier.
  4. Action: call the Rithmic / MT5 / TraderEvolution API to Disable Market Data — this switches off all of that trader's feeds, base CME included.
  5. Pod Impact: if the trader belongs to a Pod → decrement the Pod Leader's Current_Count (freeing the slot) and set the trader's Pod Status to Inactive_Hold.
  6. Notify: send the Zombie_Account_Pause email — it explains that data is paused, lists what is untouched (credentials, evaluation status, layouts, journals, trade history), notes that the Pod seat went back to the waitlist, and carries a reactivation CTA. Full copy: Ref: SES-30.
  7. Reactivation: the trader clicks the reactivation_url in the email or the Resubscribe button on the tab → runs §6.3.

What gets switched off versus what gets switched back on. Flow 12 switches every feed off in one go, but the UI puts a Resubscribe button on each card:

  • After Flow 12 runs, every feed the trader owns becomes Inactive with the Paused after 30 days without trading chip, each with its own Resubscribe button.
  • On the tab the trader reactivates one feed at a time — switching NYMEX on does not switch CBOT on.
  • The reactivation_url in the email is the exception: it is a bulk action that switches on every feed eligible for Case 1 at once, then drops the trader on the Market Data Management tab. Feeds that fall under Case 2 (new month, payment required) are not switched on and keep their Resubscribe button so the trader can check out (Ref: §6.3).

Loop protection — required. The cron scans last_trade_date < (Today − 30). A trader who reactivates a feed but does not trade leaves last_trade_date unchanged, so the next day's cron switches the feed off again, and again, until they place an order. To prevent that, Flow 12 must skip traders who have just reactivated but not yet traded:

  • Record the reactivation timestamp (for example market_data_reactivated_at) during POST /toggle-market-data.
  • Extra scan condition: only switch off when last_trade_date < (Today − 30) AND (market_data_reactivated_at IS NULL OR last_trade_date > market_data_reactivated_at).
  • In plain terms: once a trader reactivates, leave them alone until they actually place an order; the 30-day counter restarts from that order.
  • Without this rule, a trader returning from a long break loses their feed again the next morning with no idea why.

What Flow 12 does NOT do (Ref: BR_4.17.1.22):

  • It does not delete trade history, performance ledgers or account balances.
  • It does not touch positions or working orders — the Risk Engine is what flattens positions that breach overnight margin, and working orders are cancelled by the exchange itself. In practice a trader cannot sit idle for 30 days and still hold an open position.
  • It does not hard-delete the Rithmic User ID, so exchange-agreement signatures stay valid.
  • It does not reset virtual_equity and does not create a new account. Reactivating means resuming with the same balance and history.

6.10 Flow 22 — Monthly Data Fee Billing (background job)

The Flow 22 cron reads each trader's customer_vault_id to decide which schedule and action applies.

Path A — Manual APM Workflow (customer_vault_id IS NULL)

StepDetail
TriggerEOM−7 (7 days before the last day of the month)
ActionGenerate the combined invoice → send the payment link by email (Ref: SES-31) and by dashboard notification at WARN severity (Ref: BR_4.17.1.20). The link points at the standard Checkout page, pre-configured with product_id = MARKET_DATA
What the trader doesOpens the link → picks an APM at checkout → completes the push payment themselves
RecordingProcess Payment Webhook catches the success payload → updates market_data_paid_until
EmailSES-31 Invoice_APM_emailone template whose body covers both tiers side by side. Sent exactly once at EOM−7, with no reminder ladder. The second contact, if the trader still has not paid, is the downgrade email SES-17 on the last day of the month

Path B — Automated NMI Workflow (customer_vault_id IS NOT NULL)

StepDetail
TriggerEOM−3 (3 days before the last day of the month)
QueryTraders with Market_Data_Billable == True AND Status == 'Active'
ActionCall POST /generate-invoices → the middleware computes Invoice_Amount (Ref: BR_4.17.1.6) → charge the is_default vault token through NMI
On failureThe middleware pushes an INVOICE_PAYMENT_FAILED event to Zapier (payload includes card_brand and card_last_4) → send the Urgent_Data_Payment_Required email to the trader (Ref: SES-16) and a Slack alert to Ops in #ops-general (Ref: BR_4.17.1.20) → push a WARN dashboard notification

Day 0 sweep (Path B / NMI only, last day of the month)

For traders who bought an add-on after the EOM−3 cron had already run. Their purchase payment only covers the current month, so a final sweep is needed to collect for the next one.

StepDetail
TriggerDay 0 — last day of the month, runs before the End of Month Hard Check
QueryEvery Active trader whose market_data_paid_until == TODAY
ActionCharge the is_default vault token through NMI for the next month's cycle
  • This group gets no 3-day warning. They bought after the EOM−3 cron ran, so they were never in that batch — no Urgent_Data_Payment_Required email and no WARN dashboard notification at EOM−3. Their first contact is the outcome of the Day 0 charge itself.
  • The number of charge attempts differs between the two groups (Ref: BR_4.17.1.23):
GroupAttemptsNote
Bought before EOM−32 — EOM−3 then Day 0A failure at EOM−3 triggers the email and WARN notification, leaving time to fix the card before Day 0
Bought in the last 3 days of the month1 only — Day 0No earlier attempt, so no chance to fix the card. A failure means the feed is downgraded the same day
  • 🔴 Ordering constraint the backend must respect: the End of Month Hard Check queries the database for Last_Data_Payment_Status == Failed; it does not receive a list from the sweep. So the Day 0 sweep must finish writing Last_Data_Payment_Status for every trader in the batch before the Hard Check runs. If that flag is written asynchronously (waiting on the NMI webhook) after the Hard Check has already scanned, a failed trader slips through — their feed stays on for the whole next month unpaid, while Stack Trading is still billed by CME for them.
  • Worked example: a trader buys NYMEX on Aug 29. That payment only covers August (market_data_paid_until = Aug 31). The EOM−3 cron ran on Aug 28, before the purchase, so they were not in it. The Day 0 sweep on Aug 31 catches them because market_data_paid_until == TODAY and charges for September. If that charge fails, the End of Month Hard Check runs straight afterwards the same day and switches the feed off, with no grace period.

End of Month Hard Check (both paths, last day of the month)

Runs after the Day 0 sweep on the same day, so it also catches traders who just failed in that sweep.

  1. Query traders with Market_Data_Billable == True AND Last_Data_Payment_Status == Failed.
  2. Call the Broker API (Rithmic) to downgrade the feeds. How much is switched off depends on level (Ref: BR_4.17.1.6):
    • LIVE Level 1–2: switch off every feed, base CME included.
    • LIVE Level 3+: switch off the add-ons only (NYMEX / CBOT / COMEX); base CME keeps running because the firm pays for it.
  3. Set Market_Data_Billable = False.
  4. Send the Data_Feed_Downgraded email through AWS SES (Ref: SES-17) plus a CRITICAL dashboard notification.
  5. No grace period. Feeds go off at the moment of the hard check.
  6. On the tab, the downgraded feeds switch to the Inactive badge with the Suspended on [MMM DD, YYYY] – Payment couldn't be completed chip and a Resubscribe button (§6.4).

6.11 Exchange-agreement reminder modal (R|Trader Pro)

Rithmic locks the price feed at the exchange gateway until the trader logs into the R|Trader Pro desktop terminal and digitally signs the CME exchange agreements. This is a mandatory administrative step that happens outside the web app — the system can only remind and resend instructions; it cannot sign on the trader's behalf.

  1. The trader logs into the dashboard.
  2. The frontend calls GET /check-market-data-status once and reads the signature status.
  3. If the trader has not signed with Rithmic, the Action Required: Exchange Agreements Pending modal opens immediately on the Command tab (Ref: §9.6).
  4. The trader has two options:
    • Resend InstructionsPOST /resend-rtrader-instructions {user_id} → triggers Zapier Flow 39, which emails step-by-step instructions for logging into R|Trader Pro and signing the CME, COMEX, CBOT and NYMEX agreements.
    • Cancel → closes the modal. The trader carries on using the dashboard normally — navigating any tab, buying other packages and checking out add-ons are all unaffected (Ref: BR_4.17.1.14).
  5. While the agreement is unsigned, the modal reopens at every subsequent login.
  6. Once the trader signs in R|Trader Pro, the next login's GET /check-market-data-status reports it as signed → the modal stops appearing and the reminder banner disappears (Ref: BR_4.17.1.15).

This modal does NOT block add-on purchases. An unsigned trader can still subscribe and pay — Rithmic gates at the data-stream layer, so the only consequence is that no data flows until they sign. Ref: BR_4.17.1.14.

7. Exceptional Flow

#SituationHandling
1Trader logs in without having signed the Rithmic exchange agreementThe Action Required: Exchange Agreements Pending modal opens on the Command tab, alongside the reminder banner. Both reappear at every login until the agreement is signed. The modal is dismissible and blocks neither navigation nor purchases. Ref: §6.11, §9.6, BR_4.17.1.15
1aTrader buys an add-on while unsigned, pays, and then sees no dataNot a system fault — Rithmic releases no data until the agreement is signed, and the trader is still billed for that month. Refund requests for this go to Stack Trading support; the dashboard does not handle them
2The charge inside the Subscribe modal failsClose the payment modal and show Payment Failed, confirming that no subscription was created and nothing was charged. The error line branches by method: card → quote the last four digits; APM → name the method. Ref: §9.5 row 2
3Trader deletes a card that funds a subscriptionDeletion is blocked and Card In Use is shown. Ref: §6.7
4The is_default card has expiredThe card shows an Expired badge but still works normally in the UI. The system does not swap cards on the trader's behalf. At the next charge Flow 22 fails, and if nothing is collected by month end the feed is switched off. Changing the card is the trader's job. Ref: BR_4.17.1.11
5GET /system/status returns no payment methodsThe Alternative Payment Method block in the Subscribe modal renders no tiles. The frontend must not hardcode a fallback list. Ref: BR_4.17.1.13
6Apple Pay / Google Pay does not return the underlying card detailsThe method row must never be blank and never show an error — display the static label Apple Pay or Google Pay. Ref: BR_4.17.1.12
7Trader fails or resigns inside the window where next month is already prepaidFlow 7 runs its Refund Check (Market Data) step, which is owned by UC_4.15.2 §5 Basic Flow, Step 2 — including the branch for gateways that cannot reverse a payment automatically. Only next month's prepayment is refunded; the current month is never prorated. Ref: BR_4.17.1.17

8. Business Rules

BR_4.17.1.1: When the tab is visible

  • The Market Data Management tab is shown to LIVE traders only. Traders still in the SIM phase do not see it (Ref: BR_4.6.2.1).
  • The tab is hidden entirely from the Account tab list in either of these states:
    • Hard breachusers.status = 'Terminated' after a Level Stop (Ref: UC_4.15.2).
    • Resignationusers.status = 'Terminated' after the trader resigns (Ref: UC_4.17.2).
  • Hidden, not disabled — the tab is absent from the list and cannot be reached by deep link. In both states gateway access is already revoked and data fees have stopped, so there is nothing left to manage.

BR_4.17.1.2: Feed list, order and price source

  • The panel always renders all four feeds in a fixed order, whatever the trader owns: CME Level 2CBOTNYMEXCOMEX.
  • The CME Level 2 card carries a Popular ribbon. The other three do not.
  • Package sub-text: Full depth-of-book. This string appears only on the product line inside the Subscribe modal, never on the feed cards on the tab.
    • It is one shared string across all four feeds — not written per feed, and it does not change with status.
    • It is kept on every feed even though the wording is identical, so that it can later distinguish these packages from a future "Level 1" quotes product, which would not include full depth-of-book.
    • The frontend owns this string; it does not need to become a field on GET /market-data-products yet.
  • Asset-class description line — a different string per feed, shown on the feed cards on the tab. Each card carries only this line, without the package sub-text:
FeedAsset-class description line
CME Level 2Live market data for CME futures with real-time pricing and order activity. Default feed for all futures traders.
CBOTAgricultural and financial futures — Treasury bonds, corn, soybeans, wheat.
NYMEXEnergy futures – crude oil, natural gas, heating oil, gasoline.
COMEXMetals futures – gold, silver, copper, platinum.
  • Prices come from Table C through GET /market-data-products. Hardcoding prices is forbidden on both backend and frontend. The four variables Price_Data_CME, Price_Data_CBOT, Price_Data_NYMEX and Price_Data_COMEX are all 137.50 per month today. The figures in the wireframe are dummy data and must not be used.
  • GET /market-data-products automatically filters out products the trader already owns.

BR_4.17.1.3: Status badge matrix

Badges apply to any feed — none of them is tied to a specific one. The legend in the top right of the panel explains the three groups: Active · Inactive · Expiring.

BadgeConditionLegend group
ActiveThe feed is provisioned at the broker and paid_until_date > TodayActive
InactiveThe feed is switched off — either by Flow 12 or by a payment-failure downgradeInactive
Active until [MMM DD]The trader unsubscribed but the paid cycle has not endedExpiring
(no badge)The feed has never been subscribed to

BR_4.17.1.4: Info chip matrix

The info chip sits right after the status badge and explains why the feed is in that state. Apart from the first one, every chip applies to any feed.

ChipWhen it shows
Covered by Stack Trading · No charge to youOnly on the CME Level 2 card, and only for traders at Level 3 or above. It never appears on CBOT / NYMEX / COMEX. Level 1–2 traders pay for CME themselves, so this chip must never show for them
Paused after 30 days without tradingThe feed was paused by Flow 12 (status = Inactive_Hold)
Suspended on [MMM DD, YYYY] – Payment couldn't be completedThe feed was downgraded by Flow 22's End of Month Hard Check for non-payment
Thanks for cancelling. Your service remains active until [MMM DD, YYYY]. You can subscribe again from [MMM DD, YYYY]The trader unsubscribed and is inside the grace window. The first date is access_valid_until; the second is access_valid_until + 1 day
  • Two chips can appear on the same card at the same time. The typical case: a Level 3+ trader who has been idle for 30 days sees the CME card carrying both Covered by Stack Trading · No charge to you and Paused after 30 days without trading.
  • When both show, the who-pays chip (Covered by Stack Trading…) comes first and the status-reason chip (Paused… / Suspended…) second.

BR_4.17.1.5: Action button matrix

Each card carries exactly one button. Three action labels: Subscribe · Unsubscribe · Resubscribe. A fourth, Subscribed, is a status label rather than an action and appears only on an active CME card.

Button labelConditionButton stateClick behaviour
SubscribeThe feed has never been subscribed toEnabledOpens the Subscribe to Market Data modal — §6.1
SubscribeUnsubscribed, waiting out the paid cycle (Active until [MMM DD])Disabled— (prevents a duplicate charge at the gateway)
ResubscribeFeed Inactive because of Flow 12 (30 days without trading)EnabledBranches on market_data_paid_until — free if still inside the paid month, checkout if not. §6.3
ResubscribeFeed Inactive because of a failed paymentEnabledOpens the Subscribe to Market Data modal — payment required. §6.4
UnsubscribeFeed is Active and is not CMEEnabledOpens the cancellation confirmation modal — §6.2
SubscribedCME Level 2 card only, while CME is ActiveDisabled
  • Subscribed is always disabled and never clickable. CME is the mandatory base feed for every futures trader, so there is no cancel action for it.
  • CME can still show Resubscribe when its feed has been switched off — either because Flow 12 switched everything off, or because a Level 1–2 trader did not pay and the Hard Check took CME down too.
  • Resubscribe does not always mean a charge. Whether payment is required is decided by market_data_paid_until, not by the label. Full two-case matrix plus the Level 3+ CME exception: Ref: §6.3.

BR_4.17.1.6: Who pays — split by level

LevelBase CME Level 2Add-ons (CBOT / NYMEX / COMEX)market_data_billableInvoice_Amount formula
LIVE Level 1–2Trader pays 100%Trader paysTrue from day 1Total_Market_Data_Cost
LIVE Level 3+The firm (Stack Trading) paysTrader paysTrue if any add-onTotal_Market_Data_Cost − Base_CME_Data_Cost
  • Display consequence: the Covered by Stack Trading · No charge to you chip only appears from Level 3 up (Ref: BR_4.17.1.4).
  • Downgrade consequence: a Level 1–2 non-payer loses every feed including CME; a Level 3+ non-payer loses only the add-ons (Ref: §6.10).
  • Level 3 reimbursement perk: on reaching Level 3, GET /financial/calculate-data-refund totals every MARKET_DATA_BASE charge the trader paid at Levels 1–2 and refunds it in full. Add-ons (MARKET_DATA_ADDON) are not refunded.
  • The invoices table records both line types: fee_type = 'MARKET_DATA_BASE' (Levels 1–2) and fee_type = 'MARKET_DATA_ADDON' (any level). Both appear on the Billing tab (Ref: UC_4.6.3).

BR_4.17.1.7: Billing cycle — calendar month, prepaid, never prorated

  • CME bills by calendar month: the 1st through the last day. It is not a 30-day cycle starting from the subscription date.
  • Whatever day of the month the trader subscribes, they pay 100% of that month's fee. There is no daily proration and no partial refund.
  • After a successful payment the database is written as: market_data_paid_until = LAST DAY OF THE CURRENT CALENDAR MONTH
  • Stack Trading pays CME directly, so the trader must be charged before CME's billing period starts (prepay). A card failure at prepay time means the feed is not provisioned.
  • In the first month the trader is charged twice, and this is deliberate. Example: subscribing on Aug 13, 2026 → first charge on Aug 13 (opening the feed for the rest of August), second charge a few days before Sep 1 (prepaying September). The Subscribe modal must say so plainly (Ref: §9.2 row 6).
  • A trader who does not want the double charge has two options: wait until the 1st to buy, or skip add-ons altogether.

BR_4.17.1.8: Mid-cycle unsubscribe — a soft cancel

  • Cancelling does not switch the feed off straight away. It runs until the last day of the last calendar month paid for, which is the access_valid_until returned by Cancel Subscription.
  • During that window the card shows the Active until [MMM DD] badge, and the Subscribe / Resubscribe button must be disabled to prevent a duplicate charge at the gateway.
  • The current month is never refunded, in any circumstance.
  • After access_valid_until the feed is switched off at the broker and dropped from Flow 22's next invoice run. The card returns to the not-subscribed state (no badge, Subscribe enabled).

BR_4.17.1.9: One payment method for every feed

  • Aggregated invoicing: Flow 22 produces a single Invoice_Amount per trader covering every feed. Feeds are never charged separately.
  • Single default vault token: the combined invoice is charged to the token flagged is_default in the NMI Customer Vault.
  • All-or-nothing: the combined charge succeeds or fails as one block. There is no state where one feed survives and another is switched off for payment reasons.
  • The UI must never imply per-feed payment control — no Change link or button on individual cards. There is exactly one shared billing bar at the top of the panel.
  • Flow 12 is not an unsubscribe. It only toggles the feed off at the broker; the subscription remains and Flow 22 keeps charging for the next cycle. Whether reactivation costs money is decided by market_data_paid_until (Ref: §6.3).

BR_4.17.1.10: Path A and Path B — one flag decides

  • Whether a trader has a card on file is determined solely by users.customer_vault_id:
    • Checking out with Credit Card / Apple Pay / Google Pay → the middleware charges through NMI and creates a customer_vault_idPath B.
    • Paying with an APM (T365, Dusupay, PayRetailers…) → no vault is created → customer_vault_id IS NULLPath A.
  • The vault id is created at the very first checkout (Checkout Step 6), not when an add-on is bought. Path A traders are identifiable from day one.
  • Why APMs cannot be auto-charged: Pix / UPI / Mobile Money style APMs are push payments — the user must authenticate and authorise every single transaction on their own device. This is a structural limit of that rail, and no aggregator can work around it.
  • Path A ⇒ the EOM−7 schedule with a manual invoice the trader pushes themselves. No Day 0 sweep.
  • Path B ⇒ the EOM−3 schedule with an automatic vault charge, plus the Day 0 sweep on the last day of the month for traders who bought late. Day 0 applies to NMI only. Ref: §6.10.
  • Moving from Path A to Path B: a Path A trader who later pays by card creates a customer_vault_id, but they only move to Path B from the next cycle, never mid-cycle — this avoids a double charge (already prepaid at EOM−7, then auto-charged again at EOM−3). The billing bar and the Change Payment Method modal must nevertheless show the new method immediately, so the trader knows the next charge will go through the card.

BR_4.17.1.11: Card expiry and warning badges

Every saved card row must show its expiry date and a status badge. Three states:

StateBadgeCondition
Normal(no badge)More than 60 days to expiry
Expiring soonExpires soon(Card_Expiry_Date − TODAY) <= 60 days AND NOT Is_Expired
ExpiredExpiredTODAY > Card_Expiry_Date

Formula:

  • Card_Expiry_Date = the last day of the MM/YY month printed on the card, at 23:59. A card printed 09/28 is valid until 23:59 on Sep 30, 2028.
  • Anchor on the end of the month, not the 1st of the printed month. Getting this wrong warns up to 30 days early and marks still-valid cards as expired.
  • 60 days is used because data is billed by calendar month, so 60 days is roughly two billing cycles of warning before a hard failure.

The badge warns; it does not block. The trader can still select an Expired card as the funding source and can still leave it as is_default — the system does not swap cards on their behalf. The consequence is that Flow 22 fails at the next charge, and if nothing is collected by the End of Month Hard Check the feed is switched off (§6.10). Moving to a valid card is the trader's own responsibility — the Expires soon / Expired badges exist precisely to prompt that before it is too late.

BR_4.17.1.12: Apple Pay / Google Pay shown by device

  • Apple Pay and Google Pay are never shown together. Render exactly one wallet button, chosen by the device in use:
    • Apple devices (iPhone, iPad, Mac) or the Safari browser → only Apple Pay.
    • Everything else (Android, Windows, Chrome…) → only Google Pay.
  • Once a wallet is added, its row in the list shows the static label Apple Pay / Google Pay whenever the wallet API returns no underlying card details. It must never be blank and must never show an error.

BR_4.17.1.13: Payment methods rendered dynamically from GET /system/status

  • Prices come from GET /market-data-products. Payment methods come from GET /system/status. Two endpoints, two purposes — both must be called.
  • GET /system/status is the localization engine: it reads the Cloudflare IP header to infer the trader's country, looks up the Payment_Method_Config table to see which gateways are active there (NMI, T365, PayRetailers, Dusupay…), and returns an array of {label, explanatory_text, cta_text, icon_tags}.
  • The frontend must not hardcode the payment method list, labels, icons or explanatory copy — every button is drawn from this payload.
  • Country is inferred from the Cloudflare IP header, not from the billing address the trader typed in.
  • This tab reuses the Checkout payment-method component rather than building its own.

BR_4.17.1.14: Exchange-agreement reminder modal (R|Trader Pro)

  • The trader signs once with Rithmic for all exchange agreements — not four separate signatures for four feeds.
  • The only source of truth for signature status is GET /check-market-data-status, where the middleware pings the Rithmic API in real time. The frontend must not infer it from the database or from GET /market-data-status.
  • That endpoint is called once, at login — no polling. The trader can dismiss the modal and keep using the dashboard, so calling again mid-session would change nothing.

No purchase block. An unsigned trader can still subscribe to and pay for any add-on. Rithmic gates at the data-stream layer — it releases no market data to the terminal until the trader signs on their side. So the trader can buy and pay; they simply see no data flowing. GET /check-market-data-status therefore acts as the condition for showing the reminder, not as a purchase gate.

Trigger: on login. The Action Required: Exchange Agreements Pending modal opens as soon as the trader logs in, on the dashboard's Command tab. While unsigned, it reopens at every later session. It stops once the trader has signed with Rithmic.

Modal content:

  • Header: Action Required: Exchange Agreements Pending
  • Body: You must log into the R|Trader Pro desktop terminal to digitally sign your CME exchange agreements. Your data feeds cannot activate until this step is complete.
  • Two controls: a Cancel button (closes the modal) and a Resend Instructions button → POST /resend-rtrader-instructions {user_id} → triggers Flow 39.

The modal is dismissible. After closing it the trader can still navigate to every dashboard tab and can still check out other packages. No freeze, no lock-out, no overlay blocking navigation.

After signing: switching feeds back on after Flow 12 needs no new signature — Rithmic ties signatures to the User ID, and Flow 12 never hard-deletes it.

BR_4.17.1.15: Exchange-agreement reminder banner

  • Rithmic locks the price feed at the exchange gateway until the trader logs into R|Trader Pro and signs the mandatory digital agreements. The web application does not track that signing process in real time.
  • When GET /check-market-data-status reports the trader as unsigned, the dashboard shows a reminder banner on the Command tab telling them to log into R|Trader Pro and sign.
  • The banner appears every time the trader logs in, under the same condition as the modal in §9.6.
  • It disappears on its own once the backend confirms the agreement is signed.
  • Ref: CR-20260727-005. The banner belongs to this tab, not to Connections & Credentials (Ref: UC_4.6.1).

BR_4.17.1.16: No promo codes

The Subscribe modal has no promo code field. Market data add-ons carry no discounts.

BR_4.17.1.17: Refund policy

Two things that sound alike but are not:

ItemRefunded?Why
The month currently runningNeverNo proration. A trader who paid for August and fails on Aug 15 gets nothing back
Next month's prepaymentYes, automaticallyFlow 22 charges before month end, creating a window where the trader has paid for a month that has not started. Keeping that money after they leave invites a chargeback against our merchant accounts
  • Mechanism — owned elsewhere. Flow 7 (fail / resign) runs its Refund Check (Market Data) step. This UC does not own that step and does not restate it: the full logic — including the branch for gateways that cannot reverse a payment automatically — is specified in UC_4.15.2 §5 Basic Flow, Step 2.
  • Risk window: 3 days on Path B (charged at EOM−3); 7 days on Path A (invoiced at EOM−7).
  • Premium add-ons (MARKET_DATA_ADDON) are outside the Level 3 reimbursement of BR_4.17.1.6 — only MARKET_DATA_BASE is reimbursed.

BR_4.17.1.18: Date display format

  • Every date shown to the trader on this screen uses the US format — Month Day, Year:
    • With the year: MMM DD, YYYY — e.g. Mar 31, 2026.
    • Without the year: MMM DD — e.g. Active until Mar 31.
  • This governs the display layer only. Data sent over the API and stored in the database still follows ISO 8601 UTC — Ref: CR-08.

BR_4.17.1.19: Blocking deletion of a card that funds a subscription

  • A card that funds any active market data subscription cannot be deleted.
  • The blocking Card In Use modal lists each subscription that card funds, one per line.
  • The trader must assign a different method to those subscriptions first, then delete the card.

BR_4.17.1.20: Notification channels for payment failure and downgrade

Channel rule: the trader gets email plus a dashboard notification. Ops gets Slack. The trader never gets Slack.

Ops Slack alert — one event only. The only Slack alert this screen raises is the INVOICE_PAYMENT_FAILED notice when a Path B card charge is declined (§6.10). It goes to #ops-general (Prod C0BR8LRC5MK · Test #test-ops-general C0BR6UXRR8D) — the channel that already carries Dispute/Chargeback, MID capacity and negative balance alerts, i.e. per-trader financial exceptions. Ref: slack_channel_usage.md §14.

The end-of-month downgrade raises no Slack alert — the client only confirmed Slack for the payment-failure event, and nothing beyond that is added here.

Three dashboard notifications — one at each Flow 22 milestone, not only at downgrade. All three belong to the sixth Notification Center category, Billing & Subscriptions, and every CTA lands on this tab:

MilestoneSeverityMessage
EOM−7 — prepay reminder (Path A)WARNAction Required: Your market data renewal is due in 7 days. [Click here to pay your invoice]
EOM−3 / Day 0 — charge failed (Path B)WARNMarket Data payment failed. Please update your billing method to avoid service interruption.
Last day of the month — feed downgradeCRITICALMarket Data downgraded due to unpaid balance. Additional exchange feeds have been disabled.

WebSocket payload for all three: { severity, message, timestamp: "ISO8601", target_timestamp: "ISO8601" }.

Four emails — all copy lives in the shared registry and is referenced by ID here. All four are sent through AWS SES from support@stacktrading.com:

Email IDTemplate KeyTriggerSplit by level
Ref: SES-30Zombie_Account_PauseFlow 12 switches feeds off after 30 days without trading (§6.9)No
Ref: SES-31Invoice_APM_emailFlow 22 Path A at EOM−7 — prompts an APM trader to pay (§6.10)No — one body covers both tiers side by side
Ref: SES-16Urgent_Data_Payment_RequiredFlow 22 Path B — the card charge failed (§6.10)Yes — 2 variants. Variant A = Levels 1–2, Variant B = Level 3+
Ref: SES-17Data_Feed_DowngradedEnd of Month Hard Check switched feeds off (§6.10)No — one template for both tiers

SES-31 and SES-16 both concern unpaid money but do very different jobs. SES-31 is an invoice sent to an APM trader at EOM−7 (nobody has charged anything; the trader must pay). SES-16 is a failure notice sent to a card trader (the system charged and was declined). They are not interchangeable.

  • SES-16 branches on market_data_billable (i.e. on level), because non-payment means different things per tier: Levels 1–2 lose every feed including base CME; Level 3+ lose only the add-ons. The branch reads the flag already introduced in BR_4.17.1.6 — no new property.
  • SES-17 uses one body for both tiers. It only reports which feeds just went off and how to resubscribe — a Level 1–2 trader who loses base CME understands they must buy it back to trade, so no separate copy is needed.
  • [Feed List] in SES-16 lists only the feeds that will be switched off, not every feed on the invoice. For Level 3+ traders, base CME is on the invoice but is not switched off, so it must not appear in that list.
  • SES-16 renders the line Your {card_brand} ending in {card_last_4} was declined. Path A traders have no vault, so both variables are null and the fallback line is used: Your most recent payment via {APM_name} was unsuccessful.
  • Email copy must never promise daily retries — the system attempts at most twice (Ref: BR_4.17.1.23).
  • No dedicated dashboard payment button is built for Path A traders. They pay through the link in the email or the Extend button on the billing bar during the last 7 days of the month (§9.1 row 3). Process Payment Webhook catches the success payload and updates market_data_paid_until.

BR_4.17.1.21: Flow 12 does not deduct approved time off

  • The Flow 12 cron uses the raw last_trade_date. It does not join the DTO table and does not subtract Flow 13 approved leave.
  • A trader who takes 10 days off and then does not trade for another 20 is still caught by Flow 12 on day 30.
  • The reason: Flow 12 is a billing cost-control tool, not a termination flow. What protects a trader from losing their account is Flow 19 (Stagnation Monitor), and Flow 13 already adds DTO days to Stagnation_Deadline for that purpose.
  • The boundary: Stagnation_Deadline (plus DTO) applies only to Flow 19. Flow 12 uses the raw last_trade_date.
  • A trader returning from a long break simply clicks Resubscribe to switch their feeds back on (§6.3).

BR_4.17.1.22: Flow 12 does not touch trading data

  • Flow 12 only toggles the real-time market data feed to Off at the broker. It does not wipe trade history, performance ledgers or account balances.
  • It does not handle positions or working orders: the Risk Engine enforces overnight margin rules and flattens non-compliant positions at session end, and working orders are cancelled by the exchange. That belongs to the Command tab / risk engine, not to this UC.
  • Reactivation is a resume: the trader carries on with the same balance and trade history, not from scratch.
  • Contrast with Flow 7 (fail / resign): Flow 7 does hard-delete the broker sub-account; Flow 12 does not.

BR_4.17.1.23: Flow 22 retry policy

  • The system attempts the charge at most twice, never more: at EOM−3 and at Day 0 (the last day of the month).
  • How many attempts a trader actually gets depends on when they bought: before EOM−3 → the full 2; in the last 3 days of the month → only 1, at Day 0 (Ref: §6.10 — Day 0 sweep).
  • No daily retries. Retrying against a card the trader has not updated achieves nothing — what is needed is for the trader to fix it and pay.
  • The INVOICE_PAYMENT_FAILED webhook must carry card_brand and card_last_4 from the NMI vault, so the email can name which card was declined instead of speaking in generalities.

BR_4.17.1.24: Separate CTAs per payment mechanism

Cards and APMs work in opposite directions, so the UI must not merge them into one generic "pay" button:

MechanismHow it worksCTA
Credit / Debit Card, Apple Pay, Google PayAuto-pull — the system charges the vault token; the trader does nothingSubscribe via Credit Card
Alternative Payment Method (Pix, UPI, Bank Transfer…)Manual push — the trader must authenticate and pay on their own device every timePay via APM
  • The reason: one shared label would let APM traders assume they are auto-renewed, and they would lose their feeds because nobody told them to pay.
  • The CTA label changes the moment the trader switches radio, inside the same modal — the two buttons are never shown side by side.
  • Consistent with BR_4.17.1.10 (Path A vs Path B) and with the disclosure block at §9.2 row 6, which already explains both mechanisms in words.

9. Screen Description

9.1 Market Data Management tab

Wireframe: [BA Wireframe] Stack Trading Design/Account (Market Data Management).png · -1.png · -2.png

No.Field NameField TypeDisplaying rule / Behaviour rule
1Panel titleLabelDisplaying rule:- Fixed string Data Feed Status, top left of the panel.
2Status legendLabelDisplaying rule:- Top right of the panel, three fixed entries in order: Active · Inactive · Expiring.- Static legend only — not clickable and not data-driven. Mapping to badges: Ref: BR_4.17.1.3.
3Billing barLabel + LinkDisplaying rule:- A single row shared by all feeds, directly under the panel title. There is no per-card billing bar (Ref: BR_4.17.1.9).- Path B (customer_vault_id IS NOT NULL): All feeds billed to [card brand icon] Ending in [last4], taken from the is_default card.- Path A (customer_vault_id IS NULL): All feeds billed to [wallet icon] Alternative Payment Method.- On Path A and only during the last 7 days of the month (EOM−7 through the last day), the right of this row also shows the Remaining Extension Period: [Xd Xh Xm Xs] chip — a countdown to the end of the last day — and an Extend ([n] Feeds) button, where [n] is the number of feeds needing renewal. Outside that 7-day window neither the chip nor the button is shown.Behaviour rule:- Change link → opens the Change Payment Method modal (Ref: §9.3).- Extend ([n] Feeds) → opens the Subscribe to Market Data modal in "pay for the next cycle of every active feed" mode.- The countdown chip ticks client-side every second; when it reaches zero both the chip and the button disappear and the feeds move to whatever state the End of Month Hard Check leaves them in.
4Feed card — Feed nameLabelDisplaying rule:- Four cards in the fixed order CME Level 2CBOTNYMEXCOMEX (Ref: BR_4.17.1.2).- The CME Level 2 card carries a Popular ribbon in the top right corner; the other three do not.- The feed name is shown in full and never truncated.
5Feed card — Status badgeBadgeDisplaying rule:- Sits right after the feed name. Four possibilities: Active · Inactive · Active until [MMM DD] · no badge. Full conditions: Ref: BR_4.17.1.3.- Badges apply to any feed; none is tied to a specific one.- Date format: Ref: BR_4.17.1.18.
6Feed card — Info chipBadgeDisplaying rule:- Sits after the status badge. Four possible strings, full conditions: Ref: BR_4.17.1.4.- Covered by Stack Trading · No charge to youonly on the CME card and only for Level 3+ traders.- The other three chips (Paused after 30 days without trading, Suspended on [MMM DD, YYYY] – Payment couldn't be completed, and the thank-you chip after cancelling) apply to any feed.- Two chips can show at once on one card (e.g. a Level 3+ trader's CME card that is both firm-covered and paused by Flow 12).- The thank-you chip is the longest; if it exceeds the card width it wraps rather than truncating, because the trader needs to read both dates.
7Feed card — Description lineLabelDisplaying rule:- A fixed line per feed, always shown and unaffected by status. The four strings: Ref: BR_4.17.1.2.- Wraps on overflow; never truncated.
8Feed card — Action buttonButtonDisplaying rule:- Exactly one button per card: three action labels (Subscribe · Unsubscribe · Resubscribe) plus the status label Subscribed. Conditions, enabled/disabled state and behaviour: Ref: BR_4.17.1.5.- Subscribed appears only on the CME card and is always disabled.Behaviour rule:- Subscribe → opens the Subscribe to Market Data modal straight away, with no signature gate (BR_4.17.1.14).- Resubscribe → branches on why the feed went off (§6.3 / §6.4).- Unsubscribe → opens the cancellation confirmation modal (§9.5 row 3).- Disabled buttons accept no click and show no error tooltip.
9Exchange-agreement bannerBannerDisplaying rule:- Not part of this panel — it renders on the Command tab when GET /check-market-data-status reports the trader as unsigned. Shown at every login. Ref: BR_4.17.1.15.Behaviour rule:- Disappears once the backend confirms the agreement is signed. No real-time polling from the frontend — the signing happens inside R|Trader Pro, outside the web app.

9.2 Subscribe to Market Data modal

Wireframe: Subscribe to Market Data.png · Payment card added.png · No payment card.png · 2.1.png

No.Field NameField TypeDisplaying rule / Behaviour rule
1Modal titleLabelDisplaying rule:- Title Subscribe to Market Data, subtitle Monthly Subscription. The subtitle is a fixed string that tells the trader this is a monthly subscription, not a one-off purchase.
2Product lineLabelDisplaying rule:- Left: the feed being bought, as [FEED] Level 2 (e.g. NYMEX Level 2).- Underneath: the fixed sub-text Full depth-of-book.- Right: the feed price from GET /market-data-products (Ref: BR_4.17.1.2). Currency format: Ref: CR-11.
3Tax lineLabelDisplaying rule:- Tax ([state]) — the state comes from the trader's billing address. The backend calculates the tax; the frontend only displays it.- The whole row is hidden when tax is zero.
4Total lineLabelDisplaying rule:- Label Total, value = feed price + tax. This is the amount charged today.
5Payment mechanism selectorRadio Button (Single-selection)Displaying rule:- Two mutually exclusive options representing two very different mechanisms — cards are auto-pull, APMs are manual push (Ref: BR_4.17.1.24):  • Charged Automatically — underneath it, the card row [brand icon] •••• •••• •••• [last4] plus a Change link. If no card is saved, the radio label also reads (No payment card yet) and an + Add New link sits to the right.  • Alternative Payment Method — underneath it, a grid of APM tiles (Pix, UPI, Bank Transfer…). The tile list is rendered dynamically from GET /system/status; hardcoding is forbidden (Ref: BR_4.17.1.13).- Default selection is Charged Automatically when a card exists, otherwise Alternative Payment Method.Behaviour rule:- Changing the selection here also changes the CTA label in row 7.- Change link → opens the Change Payment Card modal (Ref: §9.3, the short variant).- + Add New link → opens the add-card panel (Ref: §9.4).- Selecting an APM tile highlights it; only one tile can be selected at a time.
6Disclosure blockLabelDisplaying rule:- A static text block under the payment selector, always shown, in exactly this order:  1. $[Total] today for [Month] access, then $[Total] every month.  2. How your subscription is billed depends on your checkout method:  3. Two bullets:    • Credit or Debit Card, Apple Pay or Google Pay: We charge your saved method automatically 3 days before the month ends. Nothing for you to do.    • Alternative Payment Methods (Crypto, Wallets, Local Methods etc): We email you an invoice 7 days before the month ends to pay manually. If left unpaid by the 1st of the month, your data feeds are downgraded.  4. CME bills by the calendar month and does not prorate fees.- This block is the only place the trader is warned about the first-month double charge (Ref: BR_4.17.1.7).
7Payment CTAButtonDisplaying rule:- The CTA label follows the mechanism selected in row 5 — there is no single shared label (Ref: BR_4.17.1.24):  • Charged Automatically selected → Subscribe via Credit Card  • Alternative Payment Method selected → Pay via APM- The amount is appended: ... ($[Total]).- Disabled only when no method has been chosen (no card saved and no APM tile selected). An Expired card is still selectable and does not disable the button (Ref: BR_4.17.1.11).Behaviour rule:- Click → POST /execute-checkout {product_id: "MARKET_DATA", addon_ids, payment_method, user_id}.- While awaiting the response the button enters a loading state and blocks further clicks to prevent a double charge.- Success → Subscription Confirmed modal. Failure → Payment Failed modal (§9.5).
8Cancel buttonButtonBehaviour rule:- Closes the modal without creating a subscription or charging anything. Returns to the tab with the feed unchanged.

9.3 Change Payment Method modal

Wireframe: Change Payment Method.png · Change Payment Method-1.png · Change Payment Card.png · Payment Method Added.png

A two-column modal: the method list on the left, and a right column whose content follows the selection on the left.

No.Field NameField TypeDisplaying rule / Behaviour rule
1Modal titleLabelDisplaying rule:- Two variants, distinguished by how the trader got here:  • Change Payment Method — entered from the Change link on the tab's billing bar. The left column shows both groups (Charged Automatically + You Pay Each Month).  • Change Payment Card — entered from the Change link inside the Subscribe modal. The left column shows only the Charged Automatically group, with no APM group, because here the trader is picking a card to be charged right now.- A back arrow (←) to the left of the title returns to the previous screen.
2Charged Automatically groupRadio Button (Single-selection)Displaying rule:- Group heading Charged Automatically, sub-text We charge this every month. Nothing for you to do.- The card list comes from Get Saved Cards; each row is radio + brand icon + •••• •••• •••• [last4] + an expiry badge if applicable (Expired / Expires soon — Ref: BR_4.17.1.11).- A wallet appears as its own row with the static label Apple Pay or Google Pay, chosen by device (Ref: BR_4.17.1.12).- The selected row is highlighted; the is_default card is selected by default.Behaviour rule:- Selecting a row → the right column shows that method's details (row 5).- A card badged Expired is still selectable — the badge warns but does not lock the radio (Ref: BR_4.17.1.11).
3Add new payment methodButtonDisplaying rule:- The last row of the Charged Automatically group, with a plus icon.Behaviour rule:- Click → the right column becomes the add-card form (Ref: §9.4). This row stays highlighted while the form is open.
4You Pay Each Month groupRadio Button (Single-selection)Displaying rule:- Present only in the Change Payment Method variant.- Group heading You Pay Each Month, sub-text We send an invoice 7 days before the month ends. If it goes unpaid, your feed are switched off.- A single option: radio + wallet icon + the label Alternative Payment Method.Behaviour rule:- Selecting it → the right column shows the How It Works block (row 6).
5Right column — Card detailsLabel + ButtonDisplaying rule:- Shown when a saved card is selected on the left. Content: brand icon + [BRAND] Ending in [last4]; a sub-line Expires [MM/YY] · Billing address: [Same as account | its own address]; a Delete button.Behaviour rule:- Delete → if the card funds a subscription, deletion is blocked and the Card In Use modal opens (§9.5 row 6); otherwise call Delete Saved Card {user_id, billing_id} and remove the row from the list.
6Right column — How It WorksLabelDisplaying rule:- Shown when Alternative Payment Method is selected on the left. Heading How It Works, three numbered steps:  1. We email you an invoice 7 days before the end of each month  2. You open the link and complete payment.  3. Your feeds stay on for the following month- Below the steps sits a consequences block whose content branches by level (Ref: BR_4.17.1.6):  • Level 3+: If we don't receive payment by the last day of the month, [list of active add-ons] are switched off. CME Level 2 stays on - Stack Trading covers it.  • Levels 1–2: states that every feed including CME Level 2 will be switched off, because at this tier the trader pays for all of it.- Final line: You'll need to do this every month.
7Cancel buttonButtonBehaviour rule:- Closes the modal and discards anything not confirmed with Done. Calls no API.
8Done buttonButtonDisplaying rule:- Disabled while the right column holds an unfinished add-card form.Behaviour rule:- If a card is selected → call Update Subscription Payment {user_id, subscription_id, new_billing_id} for every active market data subscription, set that card as is_default, close the modal and update the tab's billing bar.- If Alternative Payment Method is selected while the trader is on Path B → open the Switch to Manual Billing? warning first (§9.5 row 7); the change only executes on Confirm Switch.

9.4 Add new payment method panel

Wireframe: Add Payment Method.png

This panel occupies the right column of the Change Payment Method modal once the trader clicks Add new payment method.

No.Field NameField TypeDisplaying rule / Behaviour rule
1Wallet buttonButtonDisplaying rule:- Sits at the top of the panel, full width. Only one button is rendered: Apple Pay on Apple devices / Safari, Google Pay everywhere else (Ref: BR_4.17.1.12).- A divider with the word or sits below it.Behaviour rule:- Click → opens the wallet's payment sheet; on completion the wallet is stored as a vault method and appears in the left-hand list.
2Name on cardText FieldDisplaying rule:- Required.Validation: Ref: CR-02.
3Card numberNumber FieldDisplaying rule:- Required. Accepted brand icons (VISA, AMEX, DISCOVER, MasterCard) sit to the right of the field.Validation: Ref: CR-01. The card number is tokenized on the client; the raw number is never sent to the backend.
4Expiration (MM/YY)Number FieldDisplaying rule:- Required, MM/YY format.Validation: the value must produce a future Card_Expiry_Date under the formula in BR_4.17.1.11; an already-expired card is rejected at the form and never saved to the vault.
5CVCNumber FieldDisplaying rule:- Required.Validation: Ref: CR-01. Not stored — used only for the tokenization call.
6Billing address checkboxCheckboxDisplaying rule:- Label Billing address is the same as the address. Ticked by default.Behaviour rule:- Unticking it reveals a separate billing address form.
7Trust badgesLabelDisplaying rule:- Two static badges, SECURE SSL ENCRYPTION and PCI DSS COMPLIANT, above the submit button. Not clickable.
8Add Payment Method buttonButtonDisplaying rule:- Disabled until all four required fields are valid.Behaviour rule:- Click → tokenize → Add Saved Card {user_id, payment_token} → NMI stores it against customer_vault_id and returns {billing_id, brand, last4, exp_month, exp_year}.- Success → a Payment method added successfully toast; the new card appears in the left column pre-selected, and the right column switches to its details.- The trader must still click Done to apply the new card to their subscriptions.

9.5 Confirmation and result modals

No.ModalTriggerContent and buttons
1Subscription ConfirmedPOST /execute-checkout returns successTick icon. Title Subscription Confirmed. Line 1: [FEED] Level 2 is now active on your account. Line 2: Next charge of $[Total] on [MMM DD, YYYY], covering [next month]. — that date is Flow 22's next charge milestone (EOM−3 on Path B, EOM−7 on Path A). Note: Feed activation may take a few minutes. If prompted, sign the exchange agreement in R|Trader Pro to complete setup.Button: Back to Market Data → closes the modal and refreshes the tab.
2Payment FailedPOST /execute-checkout returns a charge errorWarning icon. Title Payment Failed. Line 1 branches by method: card → We couldn't charge your card ending in [last4].; APM → We couldn't complete your payment via [method name]. Line 2 (shared): No subscription was created and you have not been charged.Buttons: card → Try another card (opens Change Payment Card); APM → Try again (returns to the Subscribe modal with the APM tile still selected). Both cases also offer Cancel → closes, feed unchanged.
3Unsubscribe from [FEED]?Clicking Unsubscribe on a feed cardTitle Unsubscribe from [FEED]?. Sub-text: Your feed stays active until [MMM DD, YYYY] - the end of your current billing month. Body, two lines: You won't be charged again. No refund is issued for the current month. and You can subscribe again from [MMM DD, YYYY]. (= access_valid_until + 1 day).Buttons: Unsubscribe → calls Cancel Subscription; Keep Subscription → closes with no change.
4Subscription CancelledCancel Subscription returns successTick icon. Title Subscription Cancelled. Three lines: [FEED] Level 2 will remain active until [MMM DD, YYYY]. · After that date the feed will be disabled. · You can subscribe again from [MMM DD, YYYY].Button: Back to Market Data → closes and refreshes the tab; the card switches to Active until [MMM DD] with Subscribe disabled.
5Action Required: Exchange Agreements PendingTrader logs in while unsigned with RithmicIts own table: Ref: §9.6.
6Card In UseClicking Delete on a card that funds a subscriptionWarning icon. Title Card In Use. Lists one line per subscription: [Method] is funding your [FEED] Level 2 subscription. Final line: Assign a different card to that subscription before removing this one.Buttons: Change Payment Method → back to the method selector; Close → closes, card not deleted.
7Switch to Manual Billing?Clicking Done with Alternative Payment Method selected while the trader is on Path BTitle Switch to Manual Billing?. Sub-text: Your market data is currently renewed automatically. Body: By switching to a manual payment method, you must actively pay your invoice before the end of each calendar month. If an invoice remains unpaid by the last day of the month, your live data feeds will be disabled.Buttons: Confirm Switch → moves the trader to Path A; Keep Automatic → closes, card unchanged.

9.6 Action Required: Exchange Agreements Pending modal

Wireframe: Phần ngoài/-.png

This modal opens on the Command tab as soon as the trader logs in. It does not live in Settings, but it belongs to this UC because it is a direct consequence of data feed state. Ref: §6.11, BR_4.17.1.14.

No.Field NameField TypeDisplaying rule / Behaviour rule
1Modal containerPopupDisplaying rule:- Centred modal with a dimmed overlay behind it.- Location: the dashboard's Command tab, opening immediately after login.- Condition: GET /check-market-data-status reports the trader as unsigned with Rithmic. The endpoint is called once at login, with no polling.- Frequency: reopens at every login until the agreement is signed. There is no "don't show again" option.Behaviour rule:- The modal is dismissible. Once closed, the trader can navigate every tab and check out other packages. No freeze, no lock-out.- The modal does not block add-on purchases (Ref: BR_4.17.1.14).
2HeaderLabelDisplaying rule:- Fixed string Action Required: Exchange Agreements Pending. Wraps onto two lines when narrow; never truncated.
3BodyLabelDisplaying rule:- Fixed string: `You must log into the R
4Cancel buttonButtonDisplaying rule:- Secondary button below the primary one, same width. This is the control that closes the modal, matching the current design.Behaviour rule:- Click → closes the modal; the trader carries on using the dashboard.- It only hides the modal for the current session. At the next login, if the agreement is still unsigned, the modal reopens.- Calls no API and changes no state.
5Resend Instructions buttonButtonDisplaying rule:- Primary button, full modal width.Behaviour rule:- Click → POST /resend-rtrader-instructions {user_id} → triggers Zapier Flow 39, emailing step-by-step instructions for logging into R|Trader Pro and signing the CME, COMEX, CBOT and NYMEX agreements.- While awaiting the response the button enters a loading state and blocks further clicks to avoid duplicate emails.- Success → show a confirmation toast and close the modal.- Failure → keep the modal open and show an error toast so the trader can retry.

10. Open Items

Points the client has not yet confirmed, also logged in QnA_init_docs.md. This document follows the BA's proposed handling and will be updated once answers arrive.

#Open itemAffects
1Endpoint name for resending instructions: the client wrote POST /resend-rtrader-instructions, while WBS and QnA say POST /resend-r-trader-instructions. This document follows the client's wording; the backend must settle on one stringBR_4.17.1.14
2Is $137.50 the raw exchange price or does it already include a Stack Trading markup, and does it differ between Levels 1–2 and Level 3+?BR_4.17.1.2, BR_4.17.1.6
3A trader on a VPN makes GET /system/status read the wrong country from the Cloudflare IP header and see the wrong payment methods. Should a manual override be allowed?BR_4.17.1.13
4Should traders on active DTO get an email or notification before Flow 12 fires? The client confirmed no filter, but a trader returning from a long break will certainly find their feeds offBR_4.17.1.21
5The toast and popup strings on this screen have no IDs in list-toast-popup.md and are written inline here. They should be given IDs and referenced instead§9.5, §9.6
6The reminder modal is closed with Cancel, which we read as hiding it for the session and reopening at the next login. It is not settled whether it should reopen within the same session if the trader leaves the Command tab and comes backBR_4.17.1.14, §9.6
7Do the reminder modal and banner also apply to SIM traders? CR-20260727-005 describes the banner from the SIM phase onward, but the Market Data Management tab is LIVE-onlyBR_4.17.1.1, BR_4.17.1.15
8The POD MENTORSHIP STATUS block in Zombie_Account_Pause (SES-30) is written as though every trader has a Pod seat. This document rules that it renders only when the trader has a pod_leader_idSES-30, §6.9
9The CTA in Zombie_Account_Pause reads Reactivate Market Data while the dashboard button reads Resubscribe. Two different strings for the same actionBR_4.17.1.5, SES-30
10The four emails on this screen are confirmed as sent from support@stacktrading.com. It is unclear whether that is the convention for all project SES email or only for the market data grouplist_email.md

Changelog

DateVersionUpdated itemBeforeAfterNotes
2026-09-04v2Whole document translated to English · BR_4.17.1.2 · BR_4.17.1.5 · BR_4.17.1.9BR_4.17.1.11 · BR_4.17.1.14 · BR_4.17.1.15 · BR_4.17.1.17 · BR_4.17.1.18 · BR_4.17.1.20 · BR_4.17.1.24 (new) · §6.1 · §6.3 · §6.4 · §6.4a (new) · §6.9 · §6.10 · §6.11 · §7 · §9.1 · §9.2 · §9.3 · §9.5 · §9.6 · §10v1: add-on purchases blocked while CME was unsigned; Resubscribe after Flow 12 always free; Expired cards could not be selected; date format DD MMM YYYY; Full depth-of-book shown on feed cards too; one CTA in the Subscribe modal; Extend button always visible; the banner was called a "feed lock banner" shown across the whole dashboard; the refund rule restated APM handling inline and claimed no Ops involvement was neededBlocking rule removed — an unsigned trader can still buy and pay; Rithmic gates at the data-stream layer, and the trader signs once for all agreements rather than four times. Resubscribe after Flow 12 split into two cases on market_data_paid_until — free inside the paid month, checkout in a new month; CME for Level 3+ is always free. Added §6.4a — 10 edge cases where Flow 12 and Flow 22 meet. Added to §6.9 the loop-protection rule (a trader who reactivates without trading would otherwise be switched off again the next day) and the switch-off vs switch-on scope (reactivation_url is bulk, card buttons are per feed); added to §6.10 the ordering constraint that the Day 0 sweep must finish writing its flag before the Hard Check scans. Expired cards remain selectable — the badge only warns. Date format moved to US MMM DD, YYYY. Full depth-of-book now appears only in the Subscribe modal; feed cards carry the asset-class line only. Subscribe modal splits the CTA (Subscribe via Credit Card / Pay via APM) → new BR_4.17.1.24. Extend and its countdown only appear in the last 7 days of the month. Path B gains the Day 0 sweep (NMI only); Path A → B switching happens from the next cycle, though the new method displays immediately. The banner is renamed the reminder banner and shown on the Command tab, as is the modal, which keeps its Cancel button per the design. Dashboard notifications now cover all three milestones (EOM−7, charge failure, downgrade). Added SES-31 Invoice_APM_emaila single email, no reminder ladder. The Ops Slack alert is pinned to #ops-general and registered as §14 of slack_channel_usage.md; no Slack alert is raised at downgrade. BR_4.17.1.17 now references UC_4.15.2 §5 Step 2 for the refund mechanism instead of restating itApplies QnA v18 + v19 (2026-09-04): [MDM-UI-06][MDM-UI-09], [MDM-BIZ-19], [MDM-BIZ-20], plus direct BA feedback of 2026-09-04. Open Items reduced from 14 to 10
2026-09-04v1Whole documentDid not existFirst version of UC_4.17.1 — 23 Business Rules, 6 Screen Description tables, 11 flows (Basic + 10 Alternative including Flow 12 and Flow 22), 9 Exceptional Flows, 18 Open ItemsInit Flow. Sources: wireframes in Stage 2/Settings/Market Data Management/ (24 frames), Broadcast, Settings_Market Data.docx, the [MDM-*] QnA, Zapier Flows 12/22/39, and 4 related CRs. Direct BA instructions of 2026-09-04: the four button labels (Subscribe / Resubscribe / Unsubscribe / Subscribed), device-conditional wallets, the Covered by Stack Trading chip restricted to CME at Level 3+, badges and chips applying to any feed, hiding the tab on hard breach and resignation, the date format, the Full depth-of-book sub-text, the R|Trader Pro signing popup opening on the Command tab at every login, and confirmed copy for three emails — Zombie_Account_Pause / Urgent_Data_Payment_Required (two tier variants) / Data_Feed_Downgraded — recorded in list_email.md as SES-30 / SES-16 / SES-17 and referenced from here

On this page

UC_4.17.1: Settings — Market Data Management (LIVE)Document References1. Overview2. Trigger3. Pre-conditions4. Post-conditions5. Basic Flow — Viewing the data feed list6. Alternative Flow6.1 Subscribe — buying a new feed6.2 Unsubscribe — cancelling an active feed6.3 Resubscribe — a feed paused by Flow 12Case 1 — Switching back on inside the month already paid for (no charge)Case 2 — Switching back on in a new month (payment required)Exception — CME for Level 3+ tradersExchange agreement6.4 Resubscribe — a feed switched off after a failed payment6.4a Where Flow 12 and Flow 22 meet — edge cases6.5 Changing the payment method6.6 Adding a new card6.7 Deleting a card6.8 Switching from card to Alternative Payment Method6.9 Flow 12 — The "Zombie" Protocol (background job)6.10 Flow 22 — Monthly Data Fee Billing (background job)Path A — Manual APM Workflow (customer_vault_id IS NULL)Path B — Automated NMI Workflow (customer_vault_id IS NOT NULL)Day 0 sweep (Path B / NMI only, last day of the month)End of Month Hard Check (both paths, last day of the month)6.11 Exchange-agreement reminder modal (R|Trader Pro)7. Exceptional Flow8. Business RulesBR_4.17.1.1: When the tab is visibleBR_4.17.1.2: Feed list, order and price sourceBR_4.17.1.3: Status badge matrixBR_4.17.1.4: Info chip matrixBR_4.17.1.5: Action button matrixBR_4.17.1.6: Who pays — split by levelBR_4.17.1.7: Billing cycle — calendar month, prepaid, never proratedBR_4.17.1.8: Mid-cycle unsubscribe — a soft cancelBR_4.17.1.9: One payment method for every feedBR_4.17.1.10: Path A and Path B — one flag decidesBR_4.17.1.11: Card expiry and warning badgesBR_4.17.1.12: Apple Pay / Google Pay shown by deviceBR_4.17.1.13: Payment methods rendered dynamically from GET /system/statusBR_4.17.1.14: Exchange-agreement reminder modal (R|Trader Pro)BR_4.17.1.15: Exchange-agreement reminder bannerBR_4.17.1.16: No promo codesBR_4.17.1.17: Refund policyBR_4.17.1.18: Date display formatBR_4.17.1.19: Blocking deletion of a card that funds a subscriptionBR_4.17.1.20: Notification channels for payment failure and downgradeBR_4.17.1.21: Flow 12 does not deduct approved time offBR_4.17.1.22: Flow 12 does not touch trading dataBR_4.17.1.23: Flow 22 retry policyBR_4.17.1.24: Separate CTAs per payment mechanism9. Screen Description9.1 Market Data Management tab9.2 Subscribe to Market Data modal9.3 Change Payment Method modal9.4 Add new payment method panel9.5 Confirmation and result modals9.6 Action Required: Exchange Agreements Pending modal10. Open ItemsChangelog