원클릭으로
algo-risk-test
// Verify a strategy's SL / TP / trailing stop / portfolio caps fire correctly. Uses OpenAlgo sandbox + synthetic price moves. Run this before going live.
// Verify a strategy's SL / TP / trailing stop / portfolio caps fire correctly. Uses OpenAlgo sandbox + synthetic price moves. Run this before going live.
OpenAlgo execution expert. Auto-loaded knowledge base for building algorithmic trading strategies that toggle between VectorBT backtest and OpenAlgo live execution. Triggers when user mentions OpenAlgo trading strategies, dual-mode strategies, /python self-hosted strategies, options execution (short straddle, iron condor), portfolio risk caps, or live execution with stop loss / target / trailing stop / risk management.
Validate a generated strategy and produce an upload guide for OpenAlgo's /python self-hosted strategy page. Confirms env-var reads, SIGTERM, stdout-only logging.
Generate options-only execution strategies (short straddle, iron condor). Backtest mode is intentionally disabled. Live mode uses optionsmultiorder + per-leg SL.
Run multiple strategies under one supervisor with portfolio-level risk caps (portfolio SL/TP, daily PnL limits, max concurrent positions). YAML-driven.
Set up the Python environment for OpenAlgo execution skills - venv, openalgo[indicators], vectorbt, talib, scikit-learn, xgboost. Scaffolds strategies/ folder and .env.
Generate a single-file dual-mode trading strategy. Asks for indicator library and execution type. The same file runs `--mode backtest` (VectorBT) and `--mode live` (OpenAlgo). Upload-ready for OpenAlgo /python self-hosted.
| name | algo-risk-test |
| description | Verify a strategy's SL / TP / trailing stop / portfolio caps fire correctly. Uses OpenAlgo sandbox + synthetic price moves. Run this before going live. |
| argument-hint | [strategy-file] |
| allowed-tools | Read, Write, Edit, Bash, Glob, Grep |
Smoke-test the risk manager and portfolio caps without risking real capital.
$0 = path to a strategy file (e.g. strategies/ema_crossover_SBIN/strategy.py).
If not given, list available strategies and ask.
Tell the user:
http://127.0.0.1:5000/analyzer and click "Sandbox Mode". This routes all orders to the sandbox engine, no broker.client.analyzerstatus() returns analyze_mode: True:
from openalgo import api
c = api(api_key="...", host="http://127.0.0.1:5000")
print(c.analyzerstatus())
# -> {data: {analyze_mode: True, mode: "analyze", ...}}
--mode live but orders are simulated.Read the strategy file to extract:
SYMBOL, EXCHANGERISK (sl_pct, tp_pct, trail_pct, time_exit_min)Generate a sibling risk_test.py in the same folder. Pattern:
"""
Risk verification harness for <strategy_name>.
Runs the strategy in --mode live (with OpenAlgo sandbox toggled ON).
Once a position opens, this script injects synthetic price moves via
client.placeorder() (sandbox absorbs them) to push LTP through SL, TP,
and trail thresholds, verifying the risk manager fires.
Usage:
# In one terminal:
python strategy.py --mode live
# In another:
python risk_test.py
"""
import logging, os, sys, time
from pathlib import Path
from dotenv import find_dotenv, load_dotenv
_HERE = Path(__file__).resolve().parent
for p in [_HERE, *_HERE.parents]:
c = p / ".claude" / "skills" / "algo-expert" / "rules" / "assets" / "core"
if c.exists():
sys.path.insert(0, str(c.parent)); break
from openalgo import api # noqa: E402
logging.basicConfig(level="INFO", format="%(asctime)s [%(levelname)s] %(message)s",
stream=sys.stdout)
log = logging.getLogger("risk_test")
load_dotenv(find_dotenv(usecwd=True))
# --- Read these from strategy.py ---
SYMBOL = "SBIN"
EXCHANGE = "NSE"
SL_PCT = 0.01
TP_PCT = 0.02
TRAIL_PCT = 0.008
API_KEY = os.getenv("OPENALGO_API_KEY", "")
API_HOST = os.getenv("HOST_SERVER") or os.getenv("OPENALGO_HOST", "http://127.0.0.1:5000")
client = api(api_key=API_KEY, host=API_HOST)
def assert_sandbox():
s = client.analyzerstatus()
if not s.get("data", {}).get("analyze_mode"):
log.error("OpenAlgo is NOT in sandbox mode. Toggle it on at /analyzer first.")
sys.exit(1)
def get_open_position():
pb = client.positionbook()
for r in pb.get("data", []):
if r.get("symbol") == SYMBOL and int(float(r.get("quantity", 0) or 0)) != 0:
return r
return None
def main():
assert_sandbox()
log.info("Sandbox confirmed. Waiting for strategy to open a position...")
while True:
pos = get_open_position()
if pos:
log.info("Position detected: %s", pos)
break
time.sleep(5)
entry = float(pos["average_price"])
qty = abs(int(float(pos["quantity"])))
log.info("Entry %.2f qty=%d", entry, qty)
# --- Test 1: trigger the SL by placing a counter-order at SL price ---
sl_target = entry * (1 - SL_PCT) * 0.99 # push 1% past trigger
log.info("Test SL: pushing LTP to %.2f", sl_target)
# In sandbox, the trade above is simulated. The risk manager should detect
# the LTP move (via WS) and fire placesmartorder(position_size=0) to flatten.
# Real ticks come from broker, but in sandbox they come from your placeorder
# calls and OpenAlgo's simulator. Verify by polling positionbook.
time.sleep(10)
pos_after = get_open_position()
if pos_after is None:
log.info("PASS: SL triggered, position flattened.")
else:
log.error("FAIL: position still open after SL move.")
# --- Test 2: similarly for TP and TRAIL ---
# ... (extend as needed)
if __name__ == "__main__":
main()
Tell the user how to run:
# Terminal 1: run the strategy in live mode (OpenAlgo sandbox active)
python strategies/ema_crossover_SBIN/strategy.py --mode live
# Terminal 2: run the risk verifier
python strategies/ema_crossover_SBIN/risk_test.py
Note that OpenAlgo's sandbox doesn't accept arbitrary "set LTP" commands. Real verification of the risk manager often needs:
Or: temporarily lower SL_PCT to 0.0001 (1 bp) so any tick triggers the SL - confirms the WS feed and exit path work.
If automated synthetic injection isn't possible (sandbox limitations), the user should:
verbose=True temporarily)placesmartorder(position_size=0) (check tradebook() for the closing trade)core/risk_manager.py's _check_exits() log line appears with reason=SL_PCT/TP_PCT/TRAIL| Check | How |
|---|---|
| WS connects, LTP arrives | log shows subscribe_ltp success and tick callbacks fire |
| SL triggers exit | log: EXIT trigger ... reason=SL_PCT (...) |
| TP triggers exit | log: EXIT trigger ... reason=TP_PCT (...) |
| Trailing stop locks profit | log: EXIT trigger ... reason=TRAIL (...) |
| Time exit fires | log: EXIT trigger ... reason=TIME_EXIT (...) |
Exit places placesmartorder(position_size=0) | log: Exit order placed: ... |
| Exit fill price recorded for slippage | end-of-run report shows non-zero fills |
| Portfolio cap fires | run /algo-portfolio, force a strategy to fake P&L below cap, verify SIGTERM propagation |
analyze_mode: False - real broker orders WILL fire