feat: broker-aware factory for reconcile/journal/health tools
eod_reconcile, backfill_journal and the admin health block were hardwired to AlpacaPaperClient — on a BROKER=tradier stack they would silently reconcile/report against the wrong broker. make_trading_client() honors BROKER env with no silent cross-broker fallback (missing Tradier keys => skip with reason, never fall back to Alpaca). Admin UI shows the active broker label; JSON key stays 'alpaca' for compatibility. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
13c4b61e77
commit
8c62804808
6 files changed
+127
-20
No files matched your search
@@ -0,0 +1,56 @@
|
||||
"""make_trading_client honors BROKER env with no silent cross-broker fallback."""
|
||||
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
from alpaca_paper.client import AlpacaPaperClient
|
||||
from tradier_broker.client import TradierClient
|
||||
from tradier_broker.factory import make_trading_client
|
||||
|
||||
ALPACA = {"ALPACA_API_KEY": "k", "ALPACA_SECRET_KEY": "s"}
|
||||
TRADIER = {"TRADIER_ACCESS_TOKEN": "t", "TRADIER_ACCOUNT_ID": "a"}
|
||||
|
||||
|
||||
def _env(extra):
|
||||
env = {"BROKER": "", "TRADIER_ACCESS_TOKEN": "", "TRADIER_ACCOUNT_ID": "",
|
||||
"TRADIER_ENV": "", "ALPACA_API_KEY": "", "ALPACA_SECRET_KEY": "",
|
||||
"APCA_API_KEY_ID": "", "APCA_API_SECRET_KEY": "",
|
||||
"APCA_API_BASE_URL": ""}
|
||||
env.update(extra)
|
||||
return patch.dict("os.environ", env)
|
||||
|
||||
|
||||
class FactoryTests(unittest.TestCase):
|
||||
def test_default_is_alpaca(self):
|
||||
with _env(ALPACA):
|
||||
client, label = make_trading_client()
|
||||
self.assertIsInstance(client, AlpacaPaperClient)
|
||||
self.assertEqual(label, "alpaca-paper")
|
||||
|
||||
def test_tradier_selected(self):
|
||||
with _env({**ALPACA, **TRADIER, "BROKER": "tradier"}):
|
||||
client, label = make_trading_client()
|
||||
self.assertIsInstance(client, TradierClient)
|
||||
self.assertEqual(label, "tradier-sandbox")
|
||||
self.assertIsInstance(client.data_client, AlpacaPaperClient)
|
||||
|
||||
def test_tradier_live_label(self):
|
||||
with _env({**ALPACA, **TRADIER, "BROKER": "tradier", "TRADIER_ENV": "live"}):
|
||||
_, label = make_trading_client()
|
||||
self.assertEqual(label, "tradier-LIVE")
|
||||
|
||||
def test_no_fallback_when_tradier_keys_missing(self):
|
||||
with _env({**ALPACA, "BROKER": "tradier"}):
|
||||
client, label = make_trading_client()
|
||||
self.assertIsNone(client)
|
||||
self.assertIn("TRADIER_ACCESS_TOKEN", label)
|
||||
|
||||
def test_no_alpaca_keys(self):
|
||||
with _env({}):
|
||||
client, label = make_trading_client()
|
||||
self.assertIsNone(client)
|
||||
self.assertEqual(label, "no Alpaca keys")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user