A fully automatic trading system for Indian markets (NSE equities and NIFTY / BANKNIFTY index options). Once you switch it on and set your limits, it finds trades, sizes them, checks them, places them, protects them, manages them and closes them — with no human clicking anything. Every order, from every strategy, paper or live, must first pass an 11-gate Central Risk Manager and an independent LLM second opinion before it can reach a broker.
Paper trading is the default and this repository ships paper-locked. Nothing here is financial advice. If you switch anything to live, you alone are responsible for the orders it places. Live orders also require a registered static IP address (see Prerequisites).
All screenshots in this README use made-up sample data, not a real account.
Contents: Prerequisites · What "fully automatic" means · What makes it different · How it works · Supported brokers · Phase 1 · Roadmap · Dashboard tour · Quick start · Controlling the system · Configuration · Safety design · Project layout
With autonomy_mode: autonomous (the shipped setting) a trade's whole life needs no human step:
- Find — strategies scan prices, breadth, sector strength, options chains and news all session long, and an LLM agent proposes swing and intraday ideas.
- Size — position size is calculated from your live account equity and the distance to the stop, so the rupees at risk are fixed in advance.
- Check — the Central Risk Manager runs 11 gates (kill switch, caps, loss breakers, time windows, regime, news, strategy health, margin, stop-loss, LLM review, autonomy). One failed gate and the trade never happens.
- Second opinion — a different LLM from the one that had the idea reviews it and can veto it.
- Execute — the entry is sent (simulated in paper mode, to the broker in live mode) and the protective stop is placed first.
- Manage — an order monitor and reconciler watch every position against the broker; trailing stops, targets, time stops and per-leg option stops fire on their own.
- Close — intraday positions are squared off before the close, a daily-loss breaker closes all intraday positions if the day goes wrong, and an equity floor halts trading entirely.
- Report and learn — every decision is logged, Telegram alerts report what happened, and the learning engine shrinks the size of any strategy that starts losing.
What you still do: set the limits once, keep the broker session valid (Kite needs a fresh token
each trading day; on Windows this can be automated, in Docker you paste it), and read the
reports. You can pause everything at any time with the master switch, or set
autonomy_mode: manual to stop new entries. See Controlling the system.
These are specific, checkable properties of this codebase, not marketing claims:
- The risk manager cannot be bypassed. There is one path to a broker, and every strategy goes through the same 11 gates. The limits are %-of-equity numbers in config files, so they scale with your account.
- Nothing grades its own homework. The LLM that originates an idea is deliberately excluded from reviewing it, and a missing verdict means no trade (fail closed), not a guess.
- Protection comes first. The stop is placed before the position is considered "open", option structures are defined-risk or carry per-leg stops, and swing stops are also backed by broker GTT orders.
- It fails safe. Missing data, a crashed component or a broken reconciliation blocks new trades instead of continuing blindly; a daily-loss breaker for intraday and an absolute equity floor for the whole account are built in.
- Paper first, with a written bar to go live. One code path serves paper and live, strategies start on paper, and each needs enough trades with positive after-cost expectancy before it is promoted. Backtests run at 0.10 % costs and only ever add confidence; they never replace forward results.
- Honest about edge. Strategies that failed testing are disabled or removed rather than
tuned until they pass, and
scripts/research/keeps the tests, including the failures. - Every decision is explainable. Signals, gate verdicts, LLM reasoning, orders and fills are all stored in PostgreSQL and in an append-only trade ledger, and the dashboard shows only real data, never placeholders.
- It learns, but only changes what you allow. The learning engine tracks expectancy,
calibration and failure causes and scales position size by strategy health. Automatic
parameter promotion exists but is switched off by default (
config/learning.json), and nothing ever moves a strategy from paper to live on its own — that is always a manual edit.
None of this guarantees profit. Markets can and do beat well-built systems; the design goal is to keep losses small, known in advance and survivable.
- Data in — live prices and option chains from the broker, NSE reference files (bhavcopy, instruments, holidays, expiries), fundamentals (yfinance), a news feed tagged by a background LLM, and a market-regime / breadth model. Everything is stored in PostgreSQL, which is the single source of truth for state.
- Strategy engines — each strategy enabled in
config/strategies_registry.jsonproduces a signal that already includes its entry, stop and target:- Swing (CNC) — rule-based specs (USS JSON, compiled) plus an LLM idea-generation agent.
- Intraday (MIS) — ideas are pooled and ranked as a batch; nothing is taken just because it arrived first.
- Index-options seller desk — defined-risk credit spreads and condors, expiry-day and intraday strangles with per-leg stops, a Greeks budget, IV-rank and event blackouts, and frozen rule-based adjustments.
- Central Risk Manager (CRM) — gates G0–G10 run in order: kill switch, hard caps, circuit and daily-loss breakers, time windows, regime, news veto, strategy health, portfolio and margin, stop-loss and %-of-equity sizing, LLM confirmation, autonomy mode. The first gate that fails stops the trade. No strategy can bypass the CRM.
- AI second opinion (G9) — a reviewer chain with automatic failover (Gemini, Cloudflare Workers AI, Groq, Anthropic, Ollama). The reviewer is never the model that came up with the idea. It can veto a trade but never start or enlarge one, and every verdict is written to the database.
- Execute — fills go to the paper engine (with simulated costs) unless that segment and that strategy are both switched to live. Protective stops are placed first. An order monitor and a reconciler keep the database in line with the broker, and every fill is recorded in an append-only trade ledger.
- Watch & learn — supervisor invariants, Telegram alerts and a React dashboard that shows only real data. A learning engine tracks expectancy, profit factor and slippage and feeds strategy-health scores back into gate G6. It never promotes a strategy to live on its own.
| Broker | Status | Notes |
|---|---|---|
| Paper (built-in) | ✅ Default, fully supported | Simulated fills, stops, GTT-style OCO and costs, so no order ever reaches a broker. Live market data comes from any one configured broker (Kite, Angel One or Flattrade), see below. |
| Zerodha Kite Connect | ✅ The reference broker and the only one run end to end (paid data plan; static IP for live orders) | Quotes, option chains, historical data, margins, orders, native GTT for swing stops, automated daily TOTP login. Optional: the system starts and runs paper trading without it, but options paper trading still needs Kite's option chain. |
| Flattrade | 🟡 Built, partly verified | Login, account funds, instruments, quotes and candles were checked against the live API read-only and match Kite. Order placement is switched off (live_orders_verified: false) until a 1-lot live test and Flattrade's approval for automated trading. Data is REST-only (200 calls/min, no tick feed), so it sits last in the data-provider order. Login is a manual daily browser step. |
| Angel One (SmartAPI) | 🟡 Built, not tested live | Adapter, token refresh and equity market data are covered by unit tests only; no live call or order has been made through it. Index and options data and pre-trade margin are not supported yet. |
| Upstox | 🔲 Planned | Not supported yet. See the roadmap. |
Treat Flattrade and Angel One as experimental. Do not route a live strategy to either until you have run the live-verification steps yourself.
Any single broker can run on its own: put only that broker's credentials in .env and keep it
in market_data.providers (config/global.json). A broker with no credentials is skipped at
startup, and the system refuses to start only when no data provider at all is usable (it never
falls back to mock data). launcher.py signs in each broker that has credentials, and the
dashboard shows one connection card per broker.
Orders are routed per strategy: each live entry in config/strategies_registry.json carries a
broker field. There is no default broker, no failover and no paper fallback, so a live strategy
with a missing or unconfigured broker has its signals rejected and logged. A position always exits
on the broker that opened it. Per-broker risk gating on each broker's own equity exists behind
system.per_broker_equity (off by default, because turning it on changes live sizing).
BROKER=paper | kite | angel_one in .env still selects the legacy single broker (unset =
paper). Orders go through one BrokerInterface (src/brokers/base.py); per-broker differences —
product codes, GTT support, bracket orders, websocket limits — are declared in
src/brokers/capability_matrix.json.
Exchanges and instruments: NSE cash equities (CNC delivery and MIS intraday) and NSE index options on NIFTY / BANKNIFTY, plus BSE SENSEX options for one paper strategy. Futures, commodities and currency are out of scope.
Phase 1 is a paper-first trading lab with a hardened risk core. The goal is to collect honest, after-cost forward results for each strategy before any real money is involved.
Included
- Central Risk Manager (G0–G10), %-of-equity sizing, drawdown size steps, daily-loss breaker with force-flatten, absolute equity floor, and a master paper lock.
- Paper and live execution paths that share one code path, with protective stops placed first.
- Order monitor, reconciler against the broker, GTT backup orders, append-only trade ledger.
- Independent LLM review (G9) with a multi-provider failover chain and per-purpose daily call caps.
- News ingestion and classification, market regime, breadth, and sector rotation models.
- Learning engine: expectancy, calibration of LLM confidence, failure attribution, strategy health tiers that shrink position size automatically.
- React dashboard with 17 tabs, Telegram alerts, PostgreSQL storage with auto-applied migrations.
- One-command Docker setup (
docker compose up -d --build): app, PostgreSQL and Redis. - Backtest and research scripts in
scripts/andscripts/research/, run at 0.10 % cost.
Strategies shipped (all execution_mode: "paper")
| Strategy | Segment | State |
|---|---|---|
breadth_gated_breakout |
Swing | Enabled, paper. Takes no trades while market breadth is weak. |
llm_swing_agent |
Swing | Enabled, paper. LLM proposes ideas; CRM and G9 gate them. |
llm_intraday_agent |
Intraday | Enabled, paper-locked. |
options_seller_desk_v3 |
Options | Enabled, paper. Defined-risk credit spreads on NIFTY / BANKNIFTY. |
options_intraday_short_premium2 |
Options | Enabled, paper only. SENSEX ATM short straddle: enters about 10:32, per-leg stop (25 %), exits 15:10, skips Wednesdays. Stop and times are config values. Forward data collection, not a proven edge: offline tests showed it failing once realistic stop slippage was applied. |
options_expiry_day |
Options | Enabled, paper. NIFTY expiry-day short strangle with per-leg stops. |
options_intraday_short_premium |
Options | Enabled, paper. Daily NIFTY strangle with per-leg stop. |
minervini_vcp, oneil_canslim, news_catalyst_momentum |
Swing / intraday | Disabled. Kept as reference; minervini_vcp failed its hold-out test. |
A strategy being enabled does not mean it has a proven edge. Treat every result as unproven until it clears the promotion bar in Going live.
Known limits of Phase 1
- Windows is the tested platform. Stored broker credentials use the Windows machine-wide DPAPI store; on Linux / macOS / Docker they come from environment variables and only paper trading is tested.
- Docker (
docker compose up -d --build) is a single paper-only image with the dashboard's dev server; see INSTALL.md. - Only Zerodha Kite Connect has been run end to end. Flattrade is verified read-only (orders off) and Angel One is unit-tested only; neither has placed a live order. See Supported brokers.
- Option stop-losses are enforced by the system, not by resting broker-side orders.
- Paper stop-loss fills include modelled slippage (gap, spread and impact), but real fills can still be worse, so paper P&L on option-selling strategies overstates what live would give.
Plans, not promises — none of this is in the current release. The order follows one rule: anything that protects capital comes before anything that adds trades.
Risk core, paper and live execution paths, seven options and equity strategies running in paper, LLM review, learning engine, 17-tab dashboard, Docker one-command setup.
- Broker-side protection for options. Resting stop orders for option legs so a stop survives a crash or restart of this process.
- Real assisted mode. An approve-each-trade queue in the dashboard (accept, reject or let it
time out) so
assistedactually waits for you, replacing today's unusedask_modesettings. - Promotion tooling. One report per strategy that checks the written bar (trade count, profit factor, expectancy, slippage versus model) and refuses a switch to live until it is met.
- Broker independence — built, partly verified. Done: market-data router with failover, Kite-optional startup, per-broker sign-in, per-strategy order routing, per-broker risk and reconciliation, per-broker dashboard cards. Still open: the options chain and previous-close data (breadth, sectors) still need Kite.
- More brokers: Flattrade and Angel One — adapters built, live verification pending.
Flattrade: read-only checks pass; next are a 1-lot live order test and the exchange approval
for automated trading, then switching
live_orders_verifiedon. Angel One: needs its first live data and order checks, index/options data and pre-trade margin verification. Neither is listed as supported until it has passed those runs, including how its stops behave. - Production-grade containers. Separate API, orchestrator and dashboard containers, a built (not dev-server) dashboard, and a tested live-broker login path.
- Automatic Kite session refresh in Docker without pasting a daily token.
New strategies. Added only after they pass an out-of-sample test after costs; ideas that
fail are recorded and dropped, not tuned until they pass. Candidates under research in
scripts/research/:
- Pullback-in-trend and breakout variants for swing, with breadth and sector filters.
- Intraday edges beyond the LLM agent (opening-range, last-hour behaviour), kept paper-only until after-cost expectancy is proven.
- More options structures (calendar and diagonal spreads, iron butterfly variants) with defined risk and rule-based adjustments.
- Volatility-regime strategies using IV rank, IV-versus-realised spread and term structure.
- A strategy-selection layer that sizes each strategy by its recent health instead of switching strategies on and off by hand.
Usability and reach.
- Guided setup in the dashboard (broker login, API keys, Telegram) instead of editing
.env. - A strategy builder UI on top of the USS JSON spec.
- More brokers: Upstox, validated the same way before it is listed as supported.
- Hosted / multi-account mode with per-account risk limits.
- Walk-forward and Monte-Carlo validation built into the backtester, with an out-of-sample report saved next to every strategy.
- Slippage and fill model calibrated from real fills, and smarter order slicing for larger size.
- Portfolio-level risk: correlation and sector exposure limits across strategies.
- Event-aware trading: earnings, RBI and index-rebalance calendars wired into entries and exits.
- Replay mode: re-run any past day through the full pipeline to reproduce a decision.
Have an idea? Open an issue — and see CONTRIBUTING.md for what a strategy proposal needs.
Sample data throughout. Open http://localhost:5173 after starting the system.
| Tab | What it shows |
|---|---|
| Overview — screenshot | Today's P&L, funds and margin, intraday P&L curve, market regime, breadth, FII / DII, open positions, sector strength. |
| Order Monitor+ — screenshot | Open and closed positions, swing book, GTT backup orders, monitor health and auto-actions. |
| Options Trading — screenshot | Each options structure with legs, live P&L, max profit / loss, breakevens, Greeks budget. |
| Paper Trades — screenshot | Every simulated trade across segments with LLM verdict and regime. |
| News Intel — screenshot | Classified headlines with sentiment, impact and the trading action taken. |
| Signals / Scanner — screenshot | Nightly VCP setups and relative-strength leaders. |
| Strategy Studio — screenshot | Strategy toggles, paper / live mode per strategy, backtest results and pass / fail. |
| Intelligence — screenshot | LLM and agent intelligence status. |
| Learning — screenshot | Strategy health tiers, win / loss attribution, LLM calibration, detected patterns. |
| Agent Status — screenshot | Processes, database, broker and LLM connection health. |
| System Health — screenshot | LLM provider chains, gap risk, edge decay, cost erosion. |
| Self-Healing+ — screenshot | Reconciliation runs and automatic repairs. |
| Configuration — screenshot | Live editor for every config/*.json file. |
| Alerts — screenshot | Breaches and system alerts. |
| Trades & P&L — screenshot | After-cost P&L by segment, weekly bars, cost-erosion gate. |
| Reports — screenshot | Tax and performance reports. |
| Logs | Every component's log file, with paging and download. |
| You need | For | Notes |
|---|---|---|
| An account with at least one supported broker (Zerodha Kite Connect with the paid market-data plan, Angel One or Flattrade) | Everything, including paper trading (prices, candles and option chains come from a broker) | Paper mode simulates orders but takes live data from your broker. Kite is optional, but without it options paper trading and the market-breadth and sector panels are unavailable (see Supported brokers). Kite setup and plans: INSTALL.md section 6 |
| A registered static public IP address | Live trading only | LIVE TRADING WILL NOT WORK WITHOUT IT. Zerodha rejects every API order that does not come from a static public IP registered in your Kite developer console; check your other broker's API terms for the same rule. Paper trading is not affected, because it sends no orders to the broker |
| Python 3.13+, PostgreSQL 14+, Node 20.19+ / 22+ | Running natively | Or use Docker instead (next row) |
| Docker with Compose v2 | Running with one command | Replaces the Python, PostgreSQL, Redis and Node installs |
| At least one LLM API key | AI second opinion, news tagging | Free tiers work (Gemini, Groq, Cloudflare) |
| Telegram bot | Mobile alerts (optional) |
Windows 11 is the tested platform. Full details are in INSTALL.md.
git clone https://github.com/samhitrix/Ashwax.git AshwaX && cd AshwaX
python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e ".[dev]"
cp .env.example .env # set DB_URL at minimum
createdb ashwax # empty PostgreSQL database
cd dashboard_react && npm install && cd ..
python launcher.py # then open http://localhost:5173The full step-by-step guide, including broker login, LLM keys, Telegram, running as a Windows service and troubleshooting, is in INSTALL.md.
Every control below is a plain setting in config/*.json. Change it in the dashboard
(Configuration tab) or edit the file, then restart (docker compose restart app, or restart
the launcher). The three safety switches act at different levels and the strictest one wins:
| Level | Setting | If it says "stop" |
|---|---|---|
| Whole account | operator.json → account.paper_mode_locked |
Everything is forced to paper, whatever the other files say |
| Whole system / one segment | global.json → system.master_switch and system.segments.<segment>.master_switch |
Gate G0 blocks every new trade (kill switch). The system-wide switch overrides a segment's |
| One strategy | strategies_registry.json → enabled, execution_mode |
That strategy produces nothing, or runs on paper only |
<segment> is intraday (MIS), swing (CNC) or options.
Set per segment in global.json → system.segments.<segment>.autonomy_mode (the system-wide
system.autonomy_mode is the fallback). Gate G10 enforces it on every order.
| Mode | What happens to a trade that passes all risk gates |
|---|---|
manual |
Blocked. Nothing is entered automatically. Use it to freeze new entries while open positions keep their stops and exits |
assisted |
Currently behaves like autonomous (see the note below) |
autonomous |
Entered automatically with no human in the loop |
Honest note on
assisted. The mode and itsask_modesettings exist in the config, but this release has no approve-each-trade queue yet: G10 lets anassistedtrade through, and theask_modeblock inglobal.jsonis not read by any code. The only "ask" behaviour today is automatic: when a strategy's health turns stressed, new entries are skipped until it recovers. If you want a human to approve every trade, usemanualand place the trades yourself. A real approval flow is on the roadmap.
| Setting | Values | Effect |
|---|---|---|
segments.<segment>.paper_mode |
true / false |
true: orders are simulated, nothing reaches the broker. false: real orders, real money. Segments can differ and run side by side |
segments.<segment>.shadow_mode |
true / false |
true: signals are evaluated and logged but no order is placed, not even a paper one. Good for watching a strategy without trading it |
strategies_registry.json → execution_mode |
paper / live |
Per-strategy lock. A strategy set to paper stays on paper even if its segment is live |
strategies_registry.json → llm_gate_required |
true / false |
true: the trade needs an LLM second-opinion verdict, and no verdict means no trade |
strategies_registry.json → enabled |
true / false |
Turns a strategy on or off |
Going live needs all three layers to allow it: the account unlocked, the segment's
paper_mode set to false, and the strategy's execution_mode set to live.
All in config/capital.json, as a percentage of live account equity, so every limit and every
position size scales with your account. The values below are the shipped defaults.
| Setting | Default | What it does |
|---|---|---|
account.max_loss_if_everything_open_hits_stop |
3% | Shared risk pool: the combined stop-loss distance of all open positions across all segments can't exceed this |
account.stop_all_trading_if_equity_falls_below |
25% | Absolute floor: below this the system stops trading |
account.drawdown_steps |
3% → 75%, 5% → 50%, 8% → 25%, 10% → 0% | As the account falls from its start, position size shrinks to the stated share, down to zero |
swing.max_loss_per_trade |
0.2% | Swing position size = this amount ÷ distance to the stop |
swing.max_open_trades / max_new_trades_per_day |
12 / 2 | Caps on open swing positions and new entries per day |
swing.keep_unused_cash_buffer |
10% | Cash a swing entry may never use |
intraday.max_loss_per_trade |
0.05% | Same sizing rule for intraday |
intraday.max_loss_per_day |
0.15% | When reached, every open intraday position is closed and no new entries are taken until tomorrow (close_all_positions_when_daily_loss_hit) |
options.max_structure_loss_per_strategy |
0.75% | Worst-case loss of one options structure; the number of lots is chosen to fit |
options.max_loss_per_day_per_strategy / ..._all_options_strategies |
0.25% / 0.5% | Daily loss limits for one options strategy and for all of them together |
options.max_open_strategies |
3 | Maximum simultaneous options structures |
Every key has a _note or _rule next to it in the file explaining it in detail, and the
Configuration tab shows them as you edit.
| File | Controls |
|---|---|
config/global.json |
segments (paper_mode per intraday / swing / options), LLM chains, feature flags |
config/capital.json |
every money limit, as % of live equity (shared risk pool, drawdown steps) |
config/operator.json |
hard limits and account.paper_mode_locked (master paper lock) |
config/strategies_registry.json |
which strategies are enabled; execution_mode paper/live per strategy |
config/options_settings.json |
options desk: structures, stops, Greeks budgets, adjustments |
config/market_hours.json |
market / AMO windows |
config/charges.json |
brokerage, STT, GST and stamp duty for after-cost P&L |
Every file has _note fields that explain each key. config/examples/ keeps a paper-only
baseline that a unit test checks.
- Paper first. This repo ships with
paper_mode_locked: true, every segment set topaper_mode: trueand every strategy set toexecution_mode: "paper". Going live means changing all three on purpose. - Risk before profit. Position size comes from % of live equity and the distance to the stop. A daily-loss breaker force-flattens positions and an absolute equity floor halts trading.
- Fail closed. If a required LLM verdict, breadth data or another gate input is missing, the trade is skipped. It is never guessed through.
- Backtests only add confidence. A weak backtest lowers confidence but cannot hard-block a trade by itself, and a good backtest is not enough to promote a strategy to live.
- Everything is logged. Signals, gate decisions, LLM verdicts, orders and fills are all stored and can be replayed.
| Area | Where |
|---|---|
| Orchestrator (all loops) | src/orchestrator.py |
| Central Risk Manager (G0–G10) | src/risk/crm.py, src/risk/ |
| Orders, paper engine, brokers | src/execution/, src/paper_trading/, src/brokers/ |
| Strategies (USS specs, LLM agents) | strategies/builtin/, src/strategies/ |
| Index-options seller desk | src/options/ |
| LLM providers / failover | src/llm/ |
| Market data, regime, breadth | src/market_data/, src/market/ |
| News pipeline | src/news/ |
| Supervisor / learning | src/supervisor/, src/learning/ |
| Dashboard API / UI | src/api/, dashboard_react/ |
| Config (single source of truth) | config/*.json |
| DB schema (auto-applied) | migrations/*.sql |
| Backtests / research scripts | scripts/, scripts/research/ |
pytest -qContributions are welcome — see CONTRIBUTING.md for the ground rules (risk controls, paper-first, evidence for strategies) and how to get set up.
PolyForm Noncommercial 1.0.0. You may read, run, modify and share this software for noncommercial purposes. You may not sell it, or use it to provide a paid product or service. This is a source-available license, not an open-source (OSI) license. For any commercial use, contact the author for a separate license.
