Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions .github/workflows/quality-and-security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,15 @@ jobs:
run: python -m pre_commit validate-config .pre-commit-config.yaml

- name: Run branch-enabled test coverage
# The master is importlib-loaded because its filename has spaces. Append
# every suite into one branch-enabled runtime report, then enforce the
# 54.7% repository baseline plus the stricter per-safety/broker budgets.
# Every suite lives under Tests/, mirroring the source tree. The master is
# importlib-loaded because its filename has spaces. Append every suite into
# one branch-enabled runtime report, then enforce the 54.7% repository
# baseline plus the stricter per-safety/broker budgets.
run: |
python -m coverage erase
python -m coverage run -m unittest test_nifty_multi_strategy_master
python -m coverage run --append -m unittest test_market_data_health
python -m coverage run --append -m pytest "Signal Generators" "Dependencies" "Data Extractors" -q
python -m coverage run -m unittest Tests.test_nifty_multi_strategy_master
python -m coverage run --append -m unittest Tests.test_market_data_health
python -m coverage run --append -m pytest "Tests/Signal Generators" "Tests/Dependencies" "Tests/Data Extractors" -q
python -m coverage json -o coverage.json
python -m coverage report
python scripts/check_coverage_thresholds.py coverage.json
Expand Down Expand Up @@ -123,6 +124,6 @@ jobs:
- name: Run broker contract and adapter suites
run: >
python -m pytest
"Dependencies/test_broker_contract.py"
"Dependencies/Flattrade API/test_flattrade_execution.py"
"Tests/Dependencies/test_broker_contract.py"
"Tests/Dependencies/Flattrade API/test_flattrade_execution.py"
-q
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,7 @@ htmlcov/
# reports here. They describe one development session rather than the product,
# so keep the complete workspace-private directory out of source control.
.superpowers/
# Same reasoning for the plans/specs Superpowers writes under docs/: they are a
# per-session working record, not product documentation. docs/ itself is the
# committed architecture set (hld/, lld/, adr/) -- only this subtree is ignored.
docs/superpowers/
37 changes: 24 additions & 13 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,9 @@ One process, cooperating threads:
```
Nifty Multi Strategy Front Test - Master File.py # the multithreaded paper/live runner (the "big one")
algo.py # unified CLI: fetch-data / backtest / run / setup-token / diagnose / check-env
test_nifty_multi_strategy_master.py # unittest suite for the master
test_market_data_health.py # unittest suite for the shared feed-health gates
Tests/ # EVERY test, mirroring the source tree (docs/adr/0010)
test_nifty_multi_strategy_master.py # unittest suite for the master
test_market_data_health.py # unittest suite for the shared feed-health gates
requirements.txt # exact core runtime dependencies
requirements-brokers.txt # exact Kotak/Shoonya optional live set
requirements-ai.txt # exact optional Claude Agent SDK stack
Expand All @@ -98,12 +99,13 @@ Dependencies/
check_env_config.py # `algo.py check-env` config-drift audit (read-only)
Kotak API/ -> kotak_execution.py, diagnose_kotak_symbol.py
Shoonya API/ -> NorenApi.py (vendored client), shoonya_execution.py, diagnose_shoonya_symbol.py
Flattrade API/ -> flattrade_execution.py, diagnose_flattrade_symbol.py,
test_flattrade_execution.py
Dhan API/ -> dhan_execution.py, diagnose_dhan_symbol.py, test_dhan_execution.py
Flattrade API/ -> flattrade_execution.py, diagnose_flattrade_symbol.py
Dhan API/ -> dhan_execution.py, diagnose_dhan_symbol.py
pyproject.toml # ruff + mypy quality-gate configuration
.github/workflows/quality-and-security.yml # CI: tests + compileall + ruff + mypy + bandit
scripts/check_coverage_thresholds.py # branch-coverage policy gate
docs/ # committed architecture set: hld/, lld/, adr/
# (docs/superpowers/ is a session scratchpad, gitignored)
Backtest Outputs/ # generated CSVs/logs (gitignored)
```

Expand Down Expand Up @@ -175,20 +177,29 @@ Backtest Outputs/ # generated CSVs/logs (gitign
`Dependencies/.env` against `env.example` and against the keys the code's `_env_*` calls actually
read, reporting settings missing from `.env` (an unseen in-code default is in force), mistyped or
stale keys, and knobs missing from the template. Read-only, and it prints key NAMES only — never a
value out of `.env` — so its output is safe to share. `test_repository_policy.py` imports the same
value out of `.env` — so its output is safe to share. `Tests/Dependencies/test_repository_policy.py` imports the same
helpers so CI fails when a new `_env_*` key lands without an `env.example` entry.
- **Tests:** `python -m unittest test_nifty_multi_strategy_master` (loads the master via `importlib`,
mocks `dhanhq`; broker/SDK-specific cases skip when those deps are absent). Signal-generator tests live
under `Signal Generators/`.
- **Tests:** EVERY suite lives under `Tests/`, mirroring the source tree — the test for
`Signal Generators/<X>` sits at `Tests/Signal Generators/<X>`. Run the master suite with
`python -m unittest Tests.test_nifty_multi_strategy_master` (loads the master via `importlib`,
mocks `dhanhq`; broker/SDK-specific cases skip when those deps are absent). Two rules when adding
a test: put it at the mirrored path, and keep its FILENAME unique repository-wide (pytest keys
modules by basename — there are no `__init__.py` files). A `Tests/` folder mirroring a
spaced-name source folder carries a `conftest.py` that puts the SOURCE folder on `sys.path`,
never the test folder, so tests exercise the same import resolution production uses.
- **Quality gates (run before pushing; CI enforces on Python 3.12 + 3.13):**
`python -m unittest test_nifty_multi_strategy_master`,
`python -m unittest test_market_data_health`,
`python -m pytest "Signal Generators" "Dependencies" "Data Extractors" -q`,
`python -m unittest Tests.test_nifty_multi_strategy_master`,
`python -m unittest Tests.test_market_data_health`,
`python -m pytest "Tests/Signal Generators" "Tests/Dependencies" "Tests/Data Extractors" -q`,
the branch-enabled Coverage.py run plus `scripts/check_coverage_thresholds.py`,
pip-audit of committed pins locally plus the clean resolved CI environment,
Ruff, mypy, compileall,
Bandit, and pre-commit. Coverage floors are 54.7% overall, 90% for new
Bandit, and pre-commit. Coverage floors are 68% overall, 90% for new
execution/reconciliation/data-safety modules, and 80% per broker adapter.
Judge the overall floor from CI, never from a local run: a machine with the
optional broker SDKs installed runs 7 tests CI's verify job skips and reads
~2 points high (CI measures 69.1%). The floor only ever moves UP, and only
after a CI run shows headroom -- never lower it to make a red build pass.
- **Dependencies:** install core with `pip install -r requirements.txt`; add
`requirements-ai.txt` for SL Hunting and `requirements-dev.txt` for local
gates. `requirements-brokers.txt` is the isolated upstream compatibility
Expand Down
37 changes: 24 additions & 13 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,9 @@ One process, cooperating threads:
```
Nifty Multi Strategy Front Test - Master File.py # the multithreaded paper/live runner (the "big one")
algo.py # unified CLI: fetch-data / backtest / run / setup-token / diagnose / check-env
test_nifty_multi_strategy_master.py # unittest suite for the master
test_market_data_health.py # unittest suite for the shared feed-health gates
Tests/ # EVERY test, mirroring the source tree (docs/adr/0010)
test_nifty_multi_strategy_master.py # unittest suite for the master
test_market_data_health.py # unittest suite for the shared feed-health gates
requirements.txt # exact core runtime dependencies
requirements-brokers.txt # exact Kotak/Shoonya optional live set
requirements-ai.txt # exact optional Claude Agent SDK stack
Expand All @@ -98,12 +99,13 @@ Dependencies/
check_env_config.py # `algo.py check-env` config-drift audit (read-only)
Kotak API/ -> kotak_execution.py, diagnose_kotak_symbol.py
Shoonya API/ -> NorenApi.py (vendored client), shoonya_execution.py, diagnose_shoonya_symbol.py
Flattrade API/ -> flattrade_execution.py, diagnose_flattrade_symbol.py,
test_flattrade_execution.py
Dhan API/ -> dhan_execution.py, diagnose_dhan_symbol.py, test_dhan_execution.py
Flattrade API/ -> flattrade_execution.py, diagnose_flattrade_symbol.py
Dhan API/ -> dhan_execution.py, diagnose_dhan_symbol.py
pyproject.toml # ruff + mypy quality-gate configuration
.github/workflows/quality-and-security.yml # CI: tests + compileall + ruff + mypy + bandit
scripts/check_coverage_thresholds.py # branch-coverage policy gate
docs/ # committed architecture set: hld/, lld/, adr/
# (docs/superpowers/ is a session scratchpad, gitignored)
Backtest Outputs/ # generated CSVs/logs (gitignored)
```

Expand Down Expand Up @@ -175,20 +177,29 @@ Backtest Outputs/ # generated CSVs/logs (gitign
`Dependencies/.env` against `env.example` and against the keys the code's `_env_*` calls actually
read, reporting settings missing from `.env` (an unseen in-code default is in force), mistyped or
stale keys, and knobs missing from the template. Read-only, and it prints key NAMES only — never a
value out of `.env` — so its output is safe to share. `test_repository_policy.py` imports the same
value out of `.env` — so its output is safe to share. `Tests/Dependencies/test_repository_policy.py` imports the same
helpers so CI fails when a new `_env_*` key lands without an `env.example` entry.
- **Tests:** `python -m unittest test_nifty_multi_strategy_master` (loads the master via `importlib`,
mocks `dhanhq`; broker/SDK-specific cases skip when those deps are absent). Signal-generator tests live
under `Signal Generators/`.
- **Tests:** EVERY suite lives under `Tests/`, mirroring the source tree — the test for
`Signal Generators/<X>` sits at `Tests/Signal Generators/<X>`. Run the master suite with
`python -m unittest Tests.test_nifty_multi_strategy_master` (loads the master via `importlib`,
mocks `dhanhq`; broker/SDK-specific cases skip when those deps are absent). Two rules when adding
a test: put it at the mirrored path, and keep its FILENAME unique repository-wide (pytest keys
modules by basename — there are no `__init__.py` files). A `Tests/` folder mirroring a
spaced-name source folder carries a `conftest.py` that puts the SOURCE folder on `sys.path`,
never the test folder, so tests exercise the same import resolution production uses.
- **Quality gates (run before pushing; CI enforces on Python 3.12 + 3.13):**
`python -m unittest test_nifty_multi_strategy_master`,
`python -m unittest test_market_data_health`,
`python -m pytest "Signal Generators" "Dependencies" "Data Extractors" -q`,
`python -m unittest Tests.test_nifty_multi_strategy_master`,
`python -m unittest Tests.test_market_data_health`,
`python -m pytest "Tests/Signal Generators" "Tests/Dependencies" "Tests/Data Extractors" -q`,
the branch-enabled Coverage.py run plus `scripts/check_coverage_thresholds.py`,
pip-audit of committed pins locally plus the clean resolved CI environment,
Ruff, mypy, compileall,
Bandit, and pre-commit. Coverage floors are 54.7% overall, 90% for new
Bandit, and pre-commit. Coverage floors are 68% overall, 90% for new
execution/reconciliation/data-safety modules, and 80% per broker adapter.
Judge the overall floor from CI, never from a local run: a machine with the
optional broker SDKs installed runs 7 tests CI's verify job skips and reads
~2 points high (CI measures 69.1%). The floor only ever moves UP, and only
after a CI run shows headroom -- never lower it to make a red build pass.
- **Dependencies:** install core with `pip install -r requirements.txt`; add
`requirements-ai.txt` for SL Hunting and `requirements-dev.txt` for local
gates. `requirements-brokers.txt` is the isolated upstream compatibility
Expand Down
5 changes: 3 additions & 2 deletions Dependencies/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,9 @@ log), the nightly-refreshed `all_instrument <date>.csv` Dhan instrument master (
for option-contract resolution by the runner and the Dhan adapter), and the Google
Sheets OAuth token cache when the EOD sheet writer is enabled.

(`test_market_data_health.py` lives at the repo root next to the master's own suite;
everything else in this folder is tested right here.)
(Tests for everything in this folder live at the mirrored path under `Tests/Dependencies/`,
alongside `Tests/test_market_data_health.py` and the master's own suite. See
`docs/adr/0010-tests-in-a-mirrored-tests-tree.md` for why.)

## Keeping `.env` honest
Configuration drifts in three directions at once: your `.env`, the committed
Expand Down
7 changes: 4 additions & 3 deletions Dependencies/trading_lifecycle.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

Stopping a worker thread is not the same as safely stopping a live trading
process. Once shutdown begins, new entries must stay blocked while the runner
closes every tracked leg and asks the broker whether the account is flat. A
failed close keeps the process alive in reconciliation instead of allowing it
to report a clean shutdown.
closes every tracked leg and reconciles its own execution ledger to confirmed
flat. A failed close keeps the process alive in reconciliation instead of
allowing it to report a clean shutdown. The separate account-wide audit is
advisory because the operator may also hold manual positions in that account.

This module deliberately performs no broker calls and never sleeps. The
runner drives each transition and can inspect :meth:`retry_due` from its normal
Expand Down
Loading