BACKEND & API ENGINEER
← All work

[ Python ] 5 of 6

Trading CLI

Minervini Stage 2 + VCP scanner for ~900 IDX tickers, with 18 backtests and OOS gates.

trading-cli --period 1y --json > /tmp/picks.json
~900 IDX tickersUniverse per scan
~48% (n=110)scalp_ema_5 pooled winrate
50.8% to 12.5%hr_pdl: pooled to OOS
not proven70% winrate sleeve (README finding)
~0.5%Round-trip cost model
57.1% vs 55.6%tune.py grid OOS best
  • Python 3.11+
  • pandas
  • yfinance
  • IDX/IHSG
  • Backtesting
  • Walk-forward

[ 01 ] WHAT IT IS

In plain words

It screens roughly 900 IDX/IHSG tickers each morning against the Minervini Trend Template (8 checks) plus a VCP contraction score, then plans the entry zone, stop and targets for the ones that qualify.

Each pick is also backtested across 18 strategies with real IDX fees and slippage, tagged with the market regime at entry, and re-checked walk-forward out-of-sample so a threshold is only kept when it survives unseen data.

It is for a swing trader or a screening agent that wants machine-readable output and an explicit no-trade answer instead of a forced recommendation.

[ 02 ] ARCHITECTURE

How it is put together

  • trading_cli/cli.py is the whole surface (exposed as the trading-cli script in pyproject.toml): it parses the flags, runs the scan, ranks by expectancy, splits qualifiers from near_miss, and prints the JSON that carries picks, near_miss, leaderboard, regime_pooled and wf_regime.
  • trading_cli/scan.py:scan_universe() fetches ^JKSE plus the tickers and calls trading_cli/minervini.py:trend_template(), vcp_score() and rs_vs_ihsg() before applying the regime gates (ADTV, ATR14, IHSG stage, cmf).
  • trading_cli/backtest.py holds the 18-entry STRATS table (_sig_vcp_breakout, _sig_scalp_ema_5 and so on) and backtest.run(), which fills at the next open with fees plus slippage and tags each trade through trading_cli/regime.py:tag_ihsg_stage(), tag_atr_regime() and regime_of().
  • trading_cli/validate.py:walk_forward() replays the strategies on rolling train-252 / step-60 windows for out-of-sample confirmation, while trading_cli/tune.py:tune_vcp() grids the VCP thresholds under the same gate.
  • trading_cli/entry.py:plan() converts the 20-day-high pivot into the buy zone, the tightest stop (20-day low, close minus 2 ATR, or -8%) and T1/T2/T3 targets; trading_cli/ml_filter.py:gate_pooled_n() and check_leakage() guard any future ML work.
  • Data path: trading_cli/data.py (yfinance fetch, throttle, rate-limit backoff, 4-thread batch) over trading_cli/cache.py (SQLite in WAL mode under the XDG cache dir, 12h history TTL, stale-while-revalidate).

[ 03 ] INSTALL

Set it up

cd trading-cli
python3 -m venv .venv && .venv/bin/pip install -e .   # requires Python 3.11+, yfinance>=0.2.40, pandas>=2.0, numpy>=1.24
ln -sf "$PWD/.venv/bin/trading-cli" ~/.local/bin/trading-cli   # or call .venv/bin/trading-cli directly
trading-cli --help
trading-cli --doctor   # probes yfinance and cache health

[ 04 ] QUICKSTART

See it work

  1. trading-cli --scan-only --limit 50 --period 1y — the fastest run: a qualifier table plus the NEAR MISS block, a few seconds when cached. --scan-only skips the backtest stages, so the 70% HUNT and leaderboard blocks only appear on a full run.
  2. trading-cli --ticker BBCA — one-ticker deep dive with the Trend Template checks, VCP score, entry plan and per-strategy backtest stats.
  3. trading-cli --json > picks.json then jq '.leaderboard' — the machine-readable expectancy leaderboard the agent workflow parses.
  4. trading-cli --period 2y --validate — per-window out-of-sample results for the top strategies plus the pooled wf_regime block.
  5. trading-cli --doctor — confirms the data path with a live probe of ^JKSE plus sample tickers and reports cache size.

[ 05 ] NUMBERS

What the repo states

Universe per scan

REPO STATES

~900 IDX tickers

scalp_ema_5 pooled winrate

REPO STATES

~48% (n=110)

hr_pdl: pooled to OOS

REPO STATES

50.8% to 12.5%

70% winrate sleeve (README finding)

REPO STATES

not proven

Round-trip cost model

REPO STATES

~0.5%

tune.py grid OOS best

REPO STATES

57.1% vs 55.6%

[ 06 ] TRADEOFFS

What it does not do

  1. The README's own honesty section states there is no proven 70% win-rate sleeve on daily yfinance OHLCV alone: every higher-R and divergence candidate failed both the pooled Wilson gate and the 2y walk-forward gate, and the measured ceiling is about 50% pooled win.
  2. Institutional and broker-flow filters are not built: broker concentration or a foreign net-buy streak needs an idx.co.id scrape the README calls fragile, so it stays deferred behind ml_filter.gate_pooled_n(need=100), and there is no intraday VWAP because the data path is daily yfinance only.
  3. Regime gating is deliberately soft (a -20 combo demote, not a hard veto) with fixed, untuned thresholds, so Stage 4 tape still produces candidates; changing it is gated on out-of-sample evidence at n>=100.
  4. Everything depends on Yahoo Finance daily data through trading_cli/data.py, which throttles and needs --workers 4 when it answers 401/429, so coverage and quality are only as good as that feed.

[ 07 ] SOURCE

Read the code

The full implementation, tests and documentation live in the repository.