{
"schema_version": "1.0.0",
"name": "market_data_news_sync_guard",
"description": "Timestamp-aware synchronization layer for delayed news, Tradier sandbox quotes, option quotes, candles, VWAP and TA-Lib trade monitoring. Prevents false VWAP rejects and blocks auto-entry when data is stale or unsynced.",
"environment": {
"mode": "sandbox",
"timezone": "America\/New_York",
"market_session": {
"premarket_start": "04:00:00",
"regular_start": "09:30:00",
"regular_end": "16:00:00",
"after_hours_end": "20:00:00"
}
},
"data_sources": {
"news": {
"providers": [
"benzinga",
"white_house_feed",
"truth_social_or_president_social",
"reuters_optional",
"manual_api"
],
"required_fields": [
"event_id",
"headline",
"source",
"actual_news_ts",
"received_ts",
"symbols",
"sector_tags",
"direction_hint",
"source_url"
],
"timestamp_priority": [
"actual_news_ts",
"provider_published_ts",
"received_ts"
],
"max_expected_delay_seconds": 300,
"if_delay_unknown": "mark_delay_unknown_and_sync_before_decision"
},
"equity_quotes": {
"provider": "tradier_sandbox",
"required_fields": [
"symbol",
"bid",
"ask",
"last",
"volume",
"quote_ts"
],
"poll_interval_seconds": 1,
"max_expected_delay_seconds": 300
},
"option_quotes": {
"provider": "tradier_sandbox",
"required_fields": [
"contract_symbol",
"bid",
"ask",
"last",
"open_interest",
"volume",
"quote_ts"
],
"poll_interval_seconds": 1,
"max_expected_delay_seconds": 300
},
"candles": {
"provider": "market_data_provider_or_polygon",
"timeframes": [
"1m",
"5m"
],
"required_fields": [
"symbol",
"open",
"high",
"low",
"close",
"volume",
"candle_start_ts",
"candle_end_ts",
"is_closed"
],
"use_only_closed_candles_for_vwap": true,
"minimum_closed_candles_required": {
"premarket": 3,
"regular": 2
}
}
},
"sync_policy": {
"live": {
"max_cross_source_skew_seconds": 90,
"reject_if_stale_after_seconds": 180,
"vwap_hard_reject_enabled": true,
"use_pending_price_sync": true
},
"sandbox": {
"max_cross_source_skew_seconds": 420,
"reject_if_stale_after_seconds": 600,
"vwap_hard_reject_enabled": false,
"use_pending_price_sync": true,
"delay_adjust_news_to_market_data": true,
"allow_recheck_until_seconds": 600
},
"timestamp_fields_to_compare": [
"signal.received_ts",
"signal.actual_news_ts",
"equity_quote.quote_ts",
"option_quote.quote_ts",
"last_closed_candle.candle_end_ts",
"server_now_ts"
],
"clock_drift": {
"max_server_clock_drift_seconds": 5,
"on_clock_drift_exceeded": "pause_auto_trading_and_alert"
}
},
"status_lifecycle": {
"new_signal": "pending_sync_check",
"data_not_aligned": "pending_price_sync",
"data_aligned_waiting_vwap": "pending_vwap_confirmation",
"vwap_passed": "approved_pending_risk_checks",
"risk_passed": "approved_pending_order",
"entered": "open_monitoring",
"closed": "closed",
"failed_statuses": [
"reject_stale_data",
"reject_vwap_confirmed",
"reject_wide_spread",
"reject_duplicate_position",
"reject_direction_mismatch",
"reject_monitor_not_active",
"reject_no_closed_candles",
"reject_api_error"
]
},
"sync_decision_rules": [
{
"rule_id": "SYNC_001",
"name": "Require timestamp alignment before VWAP rejection",
"logic": "If news, equity quote, option quote, and last closed candle timestamps are not aligned inside max_cross_source_skew_seconds, set status=pending_price_sync. Do not reject_vwap yet."
},
{
"rule_id": "SYNC_002",
"name": "Reject stale data only after tolerance expires",
"logic": "If any required timestamp is older than reject_if_stale_after_seconds after sync retries, set status=reject_stale_data."
},
{
"rule_id": "SYNC_003",
"name": "Use last completed candle only",
"logic": "VWAP and TA-Lib checks must use the most recent candle where is_closed=true. Never use a partially forming 1m candle for hard decisions."
},
{
"rule_id": "SYNC_004",
"name": "Sandbox delay mode",
"logic": "In sandbox, delay tolerance is wider and vwap_hard_reject_enabled=false. VWAP failure becomes pending_vwap_confirmation first, then reject_vwap_confirmed only after synchronized recheck."
}
],
"vwap_rules": {
"fast_news": {
"vwap_required_before_entry": false,
"vwap_confirmation_window_seconds": 180,
"reject_only_after_confirmation_window": true,
"must_be_time_synced_before_reject": true,
"calls_pass_if": [
"last_closed_candle.close >= vwap",
"or price_reclaimed_vwap_and_held_for_1_closed_candle"
],
"puts_pass_if": [
"last_closed_candle.close <= vwap",
"or price_rejected_vwap_and_held_below_for_1_closed_candle"
],
"on_fail_before_window_expires": "pending_vwap_confirmation",
"on_fail_after_window_expires": "reject_vwap_confirmed"
},
"a_plus": {
"vwap_required_before_entry": true,
"must_be_time_synced_before_reject": true,
"calls_pass_if": [
"last_closed_candle.close >= vwap"
],
"puts_pass_if": [
"last_closed_candle.close <= vwap"
],
"on_fail": "reject_vwap_confirmed"
},
"premarket": {
"use_premarket_vwap": true,
"regular_session_reset_at": "09:30:00",
"after_open_wait_closed_candles": 2,
"do_not_compare_premarket_news_to_regular_vwap_until_reset_complete": true
}
},
"order_entry_guards": {
"require_sync_passed": true,
"require_stop_monitor_active_before_order": true,
"require_duplicate_lock_before_order": true,
"require_direction_validation": true,
"max_option_spread_pct": {
"default": 10,
"fast_news_extreme": 15,
"sandbox_testing_allow_record_only": 50
},
"minimum_option_volume": {
"default": 100,
"large_cap_liquid_exception": 25
},
"minimum_open_interest": {
"default": 250,
"large_cap_liquid_exception": 50
},
"reject_if_option_bid_zero": true
},
"duplicate_position_lock": {
"enabled": true,
"scope": [
"trading_day",
"session",
"strategy",
"ticker",
"contract_symbol",
"direction",
"event_cluster_id"
],
"fast_news_pyramiding_allowed": false,
"reject_reason": "reject_duplicate_position",
"lock_ttl_seconds": 23400
},
"direction_classifier_rules": {
"oil_energy": {
"bullish_energy_calls": [
"oil higher",
"crude spikes",
"supply disruption",
"Hormuz closure",
"attack on oil infrastructure",
"Middle East escalation",
"sanctions tighten"
],
"bearish_energy_puts": [
"oil lower",
"ceasefire",
"de-escalation",
"peace talks progress",
"Hormuz reopening",
"supply restored",
"deal reached"
],
"on_conflict": "manual_review"
},
"semiconductors": {
"bullish_calls": [
"AI demand upside",
"raised guidance",
"major partnership",
"chip export approval",
"earnings beat with strong guidance"
],
"bearish_puts": [
"guidance cut",
"export restriction",
"bad reaction to good earnings",
"sector de-risking",
"competitive pressure"
],
"on_conflict": "manual_review"
}
},
"premarket_direction_validation": {
"enabled": true,
"required": true,
"max_put_score_when_conflicts": 79,
"max_put_score_fade_watch": 72,
"min_premarket_change_pct_for_rebound": 0.25,
"min_top_mover_inject_pct": 3,
"fade_watch_only_tickers": [
"NVDA",
"AVGO",
"BTC",
"MSTR"
],
"block_put_confirm_on_rebound_tickers": [
"NVDA",
"AMD",
"AVGO",
"INTC",
"MU",
"MRVL",
"SMCI",
"SMH"
],
"oil_fade_put_tickers": [
"XLE",
"USO"
],
"call_flip_allowed_tickers": [
"MRVL",
"SMCI",
"AAPL",
"MU",
"AMD",
"INTC",
"AVGO"
],
"ticker_alias_map": {
"BTC": "MSTR",
"BITCOIN": "MSTR"
},
"top_mover_catalyst_phrases": [
"s&p 500",
"s&p500",
"inclusion",
"index addition",
"joins s&p",
"added to the s&p"
],
"priority_inject_tickers": [
"SMCI",
"MRVL",
"MU",
"AMD",
"INTC",
"AVGO"
],
"smci_catalyst_phrases": [
"unusual options",
"heavy call",
"call volume",
"options activity",
"premarket gainer",
"shares up",
"surges",
"jumps"
],
"energy_inject_tickers": [
"XLE",
"USO"
],
"energy_catalyst_phrases": [
"crude oil",
"oil prices",
"wti",
"brent",
"hormuz",
"iran",
"israel",
"middle east",
"geopolitical",
"energy sector",
"oil spike",
"oil rally"
],
"do_not_score_put_above_80_when": [
"ticker_premarket_change_positive",
"sector_etf_positive",
"index_futures_positive",
"fresh_news_polarity_bullish"
],
"convert_to_fade_watch_when": [
"prior_day_selloff_but_current_premarket_rebound",
"gap_up_after_panic_selling",
"put_score_based_only_on_old_news"
],
"put_confirmation_required": [
"price_below_vwap",
"first_closed_candle_rejects_vwap_or_premarket_high",
"sector_etf_below_vwap",
"options_put_flow_after_open",
"bid_ask_spread_acceptable"
],
"sector_etf_map": {
"semiconductor": [
"SMH",
"SOXX"
],
"energy": [
"XLE",
"USO"
],
"crypto": [
"COIN",
"MSTR"
],
"tech_broad": [
"QQQ",
"XLK"
],
"index": [
"SPY",
"QQQ"
]
},
"ticker_sector_map": {
"NVDA": "semiconductor",
"AMD": "semiconductor",
"AVGO": "semiconductor",
"MRVL": "semiconductor",
"MU": "semiconductor",
"SMCI": "semiconductor",
"ARM": "semiconductor",
"INTC": "semiconductor",
"IBM": "semiconductor",
"XLE": "energy",
"USO": "energy",
"XOM": "energy",
"CVX": "energy",
"COIN": "crypto",
"MSTR": "crypto",
"BTC": "crypto",
"IBIT": "crypto",
"AAPL": "tech_broad",
"MSFT": "tech_broad",
"NOW": "tech_broad"
},
"index_futures_symbols": [
"QQQ",
"SPY"
],
"rebound_headline_phrases": [
"rebound",
"recovery",
"bounce",
"rally",
"gap up",
"premarket higher",
"shares up",
"joins s&p",
"inclusion"
],
"stale_selloff_phrases": [
"friday selloff",
"prior selloff",
"last week weakness",
"earnings miss",
"guidance cut",
"sector de-risking"
]
},
"ta_lib_monitoring": {
"enabled": true,
"start_before_entry_required": true,
"indicators": {
"vwap": {
"source": "closed_1m_candles"
},
"ema_9": {
"timeframe": "1m"
},
"ema_20": {
"timeframe": "1m"
},
"rsi_14": {
"timeframe": "1m"
},
"atr_14": {
"timeframe": "1m"
},
"macd": {
"timeframe": "1m"
}
},
"monitor_interval_seconds": 1,
"heartbeat_required": true,
"heartbeat_timeout_seconds": 5,
"on_monitor_failure": "block_new_entries_and_alert"
},
"exit_rules": {
"hard_stop_loss_pct": -20,
"emergency_stop_loss_pct": -30,
"profit_protection": {
"enabled": true,
"activate_at_profit_pct": 25,
"trail_from_high_pct": 15
},
"spread_exit_guard": {
"if_spread_pct_above": 25,
"use_limit_near_bid_for_exit": true,
"max_exit_retry_seconds": 30,
"after_retry_use_marketable_limit": true
},
"stale_quote_exit_guard": {
"max_quote_age_seconds_live": 10,
"max_quote_age_seconds_sandbox": 420,
"on_stale_quote": "pause_exit_once_and_retry_quote",
"max_retries": 3
},
"sell_to_close_required_on_stop": true
},
"sync_algorithm_pseudocode": {
"data_is_time_aligned": [
"collect actual_news_ts, received_ts, equity_quote_ts, option_quote_ts, last_closed_candle_end_ts",
"remove nullable actual_news_ts only if provider did not provide it",
"newest=max(timestamps)",
"oldest=min(timestamps)",
"skew_seconds=newest-oldest",
"return skew_seconds <= config.sync_policy[mode].max_cross_source_skew_seconds"
],
"vwap_gate": [
"if not data_is_time_aligned: status=pending_price_sync",
"else if no last closed candles: status=reject_no_closed_candles",
"else if strategy=fast_news and vwap fails before confirmation window: status=pending_vwap_confirmation",
"else if vwap fails after confirmation window: status=reject_vwap_confirmed",
"else status=approved_pending_risk_checks"
],
"entry_gate": [
"confirm sync passed",
"confirm duplicate lock acquired",
"confirm option spread acceptable",
"confirm direction matches catalyst",
"confirm TA-Lib monitor heartbeat active",
"place order only after all checks pass"
]
},
"logging": {
"log_every_signal": true,
"log_path": "logs\/sync_guard\/",
"fields": [
"event_id",
"event_cluster_id",
"strategy",
"ticker",
"direction",
"contract_symbol",
"actual_news_ts",
"received_ts",
"equity_quote_ts",
"option_quote_ts",
"last_closed_candle_end_ts",
"server_now_ts",
"cross_source_skew_seconds",
"data_delay_seconds",
"vwap",
"last_closed_price",
"vwap_result",
"status_before",
"status_after",
"reject_reason",
"option_bid",
"option_ask",
"option_mid",
"spread_pct",
"monitor_heartbeat_ts",
"order_id",
"position_id"
],
"dashboard_alerts": [
"pending_price_sync_over_120_seconds",
"reject_stale_data",
"reject_vwap_confirmed",
"duplicate_position_attempt",
"stop_monitor_not_active",
"hard_stop_triggered",
"tradier_sell_to_close_failed"
]
},
"test_cases": [
{
"name": "Delayed news plus delayed sandbox quotes should not reject VWAP immediately",
"input": {
"strategy": "fast_news",
"mode": "sandbox",
"news_delay_seconds": 300,
"quote_delay_seconds": 300,
"candle_delay_seconds": 240,
"initial_vwap_fail": true
},
"expected_status": "pending_price_sync"
},
{
"name": "Synced put below VWAP should pass",
"input": {
"direction": "put",
"last_closed_price_relation_to_vwap": "below",
"data_synced": true
},
"expected_status": "approved_pending_risk_checks"
},
{
"name": "Synced put above VWAP after confirmation window should reject",
"input": {
"direction": "put",
"last_closed_price_relation_to_vwap": "above",
"data_synced": true,
"confirmation_window_expired": true
},
"expected_status": "reject_vwap_confirmed"
},
{
"name": "Duplicate same contract must reject before order",
"input": {
"existing_open_position": true,
"same_contract_symbol": true
},
"expected_status": "reject_duplicate_position"
},
{
"name": "Stop monitor inactive blocks entry",
"input": {
"ta_lib_monitor_heartbeat_active": false
},
"expected_status": "reject_monitor_not_active"
}
],
"deployment_safety": {
"auto_trading_allowed_in_sandbox": false,
"paper_trade_only_until_tests_pass": true,
"minimum_required_passing_tests": [
"sync_timestamp_alignment",
"vwap_pending_not_false_reject",
"duplicate_lock",
"spread_filter",
"stop_loss_sell_to_close",
"monitor_heartbeat"
],
"manual_override_allowed": true
}
}