feat(reflection): configurable alpha benchmark for non-US tickers

SPY was hardcoded as the alpha benchmark in both the return-fetch
path and the reflection label, which produced meaningless alpha for
.NS / .T / .HK / .L / .TO / .AX / .BO listings — FX drift between a
local-currency stock and a USD index dominates the spread.

DEFAULT_CONFIG now exposes benchmark_ticker (explicit override) and
benchmark_map (suffix → regional index, with SPY as the empty-suffix
default). TRADINGAGENTS_BENCHMARK_TICKER joins the env-overlay table.
Trading graph resolves the benchmark once per ticker and threads it
through to both _fetch_returns and reflect_on_final_decision, so the
alpha label reads "Alpha vs ^N225" for Tokyo listings, "Alpha vs ^HSI"
for Hong Kong, etc., instead of the misleading "Alpha vs SPY".
This commit is contained in:
Yijia-Xiao committed 2026-05-11 09:14:28 +00:00
1 parent 819e813a14
commit 78d063dc5c
4 files changed
+151 -15

No files matched your search

+5 -1
View File
@@ -33,11 +33,15 @@ class Reflector:
final_decision: str,
raw_return: float,
alpha_return: float,
benchmark_name: str = "SPY",
) -> str:
"""Single reflection call on the final trade decision with outcome context.
Used by Phase B deferred reflection. The final_trade_decision already
synthesises all analyst insights, so no separate market context is needed.
``benchmark_name`` is the label used for the alpha line (e.g. ``"SPY"``
for US tickers, ``"^N225"`` for ``.T`` listings); defaults to SPY for
callers that haven't been updated to thread the benchmark through.
"""
messages = [
("system", self.log_reflection_prompt),
@@ -45,7 +49,7 @@ class Reflector:
"human",
(
f"Raw return: {raw_return:+.1%}\n"
f"Alpha vs SPY: {alpha_return:+.1%}\n\n"
f"Alpha vs {benchmark_name}: {alpha_return:+.1%}\n\n"
f"Final Decision:\n{final_decision}"
),
),