config: drop the dead oanda.account_id (auto-execution leftover), keep it tolerated
The candle provider needs only oanda.api_token + base_url; account_id belonged to the
auto-execution daemon removed 2026-09-03 (31002cb). Removed from config.json.example and
the unused oanda_account_id() accessor deleted; the key stays in _KNOWN_OANDA so existing
config.json files keep loading. CLAUDE.md env-var list updated. Test locks all three.
Suite: 464 passed.
Claude-Session: https://claude.ai/code/session_01RWV2yLt3YXHHGVYHSQU2EE
This commit is contained in:
@@ -39,7 +39,7 @@ Python 3.12; a `venv/` exists in-repo. Dependencies in `requirements.txt` (numpy
|
|||||||
|
|
||||||
## Configuration & credentials
|
## Configuration & credentials
|
||||||
|
|
||||||
Precedence for every credential/deployment setting: **env var → config.json → refuse to run** (no hardcoded fallbacks). A gitignored repo-root `.env` is loaded at `app_config` import via `os.environ.setdefault`. `config.json` (gitignored; schema in `config.json.example`) holds secrets plus deployment settings: `data_providers.active` (the live-feed switch), `data_providers.streaming` (optional tick-stream provider for the level-breach monitor), `scanning.pairs`/`timeframes`, per-pair `blocked_hours_utc`, `log_level`. Key env vars: `TELEGRAM_TOKEN`, `TELEGRAM_CHAT_ID`, `TELEGRAM_CHANNEL_ID`, `TWELVE_DATA_API_KEY`, `TIINGO_API_KEY`, `OANDA_ACCOUNT_ID`/`OANDA_API_TOKEN`/`OANDA_BASE_URL`, `DEEPSEEK_API_KEY` (news LLM; the `deepseek` config.json block holds model/enabled/timeout/daily cap). The `agent_panel` config.json block (all-defaults = feature dark) controls the advisory LLM agent panel: `enabled`, per-surface `telegram`/`dashboard` toggles, `min_quality`, `max_panels_per_day`, `reuse_ttl_seconds`, plus the technical-payload enrichment knobs `candles_enabled`/`candle_bars_primary`/`candle_bars_confirm`. The dark-by-default `market_outlook` block controls the hourly advisory market brief: `enabled`, `telegram`, `max_per_day`, `candles_bars`; `MARKET_OUTLOOK_ENABLED` overrides its enabled setting. The dark-by-default `violent_watch` block controls the display-only violent-move watch: `enabled`, `alert_line`, `headsup`, `max_headsup_per_day`, `headsup_min_level` (`"watch"`/`"hot"`); `VIOLENT_WATCH_ENABLED` overrides its enabled setting.
|
Precedence for every credential/deployment setting: **env var → config.json → refuse to run** (no hardcoded fallbacks). A gitignored repo-root `.env` is loaded at `app_config` import via `os.environ.setdefault`. `config.json` (gitignored; schema in `config.json.example`) holds secrets plus deployment settings: `data_providers.active` (the live-feed switch), `data_providers.streaming` (optional tick-stream provider for the level-breach monitor), `scanning.pairs`/`timeframes`, per-pair `blocked_hours_utc`, `log_level`. Key env vars: `TELEGRAM_TOKEN`, `TELEGRAM_CHAT_ID`, `TELEGRAM_CHANNEL_ID`, `TWELVE_DATA_API_KEY`, `TIINGO_API_KEY`, `OANDA_API_TOKEN`/`OANDA_BASE_URL` (the data feed needs no account id; a legacy `oanda.account_id` key is tolerated and ignored), `DEEPSEEK_API_KEY` (news LLM; the `deepseek` config.json block holds model/enabled/timeout/daily cap). The `agent_panel` config.json block (all-defaults = feature dark) controls the advisory LLM agent panel: `enabled`, per-surface `telegram`/`dashboard` toggles, `min_quality`, `max_panels_per_day`, `reuse_ttl_seconds`, plus the technical-payload enrichment knobs `candles_enabled`/`candle_bars_primary`/`candle_bars_confirm`. The dark-by-default `market_outlook` block controls the hourly advisory market brief: `enabled`, `telegram`, `max_per_day`, `candles_bars`; `MARKET_OUTLOOK_ENABLED` overrides its enabled setting. The dark-by-default `violent_watch` block controls the display-only violent-move watch: `enabled`, `alert_line`, `headsup`, `max_headsup_per_day`, `headsup_min_level` (`"watch"`/`"hot"`); `VIOLENT_WATCH_ENABLED` overrides its enabled setting.
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
|
|||||||
+4
-6
@@ -89,6 +89,10 @@ _KNOWN_TOP = {"telegram", "data_providers", "scanning", "pairs", "log_level",
|
|||||||
"oanda", "deepseek", "agent_panel", "market_outlook",
|
"oanda", "deepseek", "agent_panel", "market_outlook",
|
||||||
"violent_watch", "signal_log"}
|
"violent_watch", "signal_log"}
|
||||||
_KNOWN_OANDA = {
|
_KNOWN_OANDA = {
|
||||||
|
# "account_id" is TOLERATED but ignored: it belonged to the auto-
|
||||||
|
# execution daemon removed 2026-09-03 (last commit 31002cb). The candle
|
||||||
|
# provider needs only api_token + base_url; older config.json files
|
||||||
|
# still carry the key and must keep loading.
|
||||||
"account_id", "api_token", "base_url",
|
"account_id", "api_token", "base_url",
|
||||||
}
|
}
|
||||||
_KNOWN_DEEPSEEK = {
|
_KNOWN_DEEPSEEK = {
|
||||||
@@ -458,12 +462,6 @@ def provider_api_key(
|
|||||||
|
|
||||||
# ── Oanda resolution helpers (env → config.json → default) ───────────
|
# ── Oanda resolution helpers (env → config.json → default) ───────────
|
||||||
|
|
||||||
def oanda_account_id(app: Optional[AppConfig] = None) -> str:
|
|
||||||
app = app or get_app_config()
|
|
||||||
return os.environ.get("OANDA_ACCOUNT_ID") or str(
|
|
||||||
app.oanda_settings.get("account_id", ""))
|
|
||||||
|
|
||||||
|
|
||||||
def oanda_api_token(app: Optional[AppConfig] = None) -> str:
|
def oanda_api_token(app: Optional[AppConfig] = None) -> str:
|
||||||
app = app or get_app_config()
|
app = app or get_app_config()
|
||||||
return os.environ.get("OANDA_API_TOKEN") or str(
|
return os.environ.get("OANDA_API_TOKEN") or str(
|
||||||
|
|||||||
@@ -26,7 +26,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"oanda": {
|
"oanda": {
|
||||||
"account_id": "REPLACE_WITH_ACCOUNT_ID",
|
|
||||||
"api_token": "REPLACE_WITH_API_TOKEN",
|
"api_token": "REPLACE_WITH_API_TOKEN",
|
||||||
"base_url": "https://api-fxpractice.oanda.com"
|
"base_url": "https://api-fxpractice.oanda.com"
|
||||||
},
|
},
|
||||||
|
|||||||
+15
@@ -10491,6 +10491,21 @@ def _():
|
|||||||
os.remove(path)
|
os.remove(path)
|
||||||
|
|
||||||
|
|
||||||
|
@test("app_config: legacy oanda.account_id is tolerated and ignored (auto-execution removed 2026-09-03)")
|
||||||
|
def _():
|
||||||
|
import copy
|
||||||
|
import app_config as _ac
|
||||||
|
payload = copy.deepcopy(_FULL_CFG)
|
||||||
|
payload.setdefault("oanda", {})["account_id"] = "101-004-LEGACY-001"
|
||||||
|
payload["oanda"].setdefault("api_token", "tok")
|
||||||
|
app = load_app_config(_write_json(payload)) # must NOT raise
|
||||||
|
assert app.oanda_settings.get("api_token") == payload["oanda"]["api_token"]
|
||||||
|
assert not hasattr(_ac, "oanda_account_id"), "dead accessor must stay deleted"
|
||||||
|
assert "account_id" not in open("config.json.example").read(), \
|
||||||
|
"the example must not advertise a key nothing reads"
|
||||||
|
assert _ac.oanda_api_token(app) == payload["oanda"]["api_token"]
|
||||||
|
|
||||||
|
|
||||||
# ══════════════════════════════════════════════════════════════════════
|
# ══════════════════════════════════════════════════════════════════════
|
||||||
# SUMMARY
|
# SUMMARY
|
||||||
# ══════════════════════════════════════════════════════════════════════
|
# ══════════════════════════════════════════════════════════════════════
|
||||||
|
|||||||
Reference in New Issue
Block a user