About algo-portfolio
A skill that guides setup and operation of a multi-strategy OpenAlgo portfolio runner. It uses a YAML configuration and global risk caps, runs strategies in isolated subprocesses, and monitors aggregate P&L; backtests run independently per strategy rather than as a merged portfolio.
Key features
- 01Configure portfolios with YAML
- 02Run strategies in isolated subprocesses
- 03Monitor aggregate P&L and global caps
- 04Halt strategies when caps are breached
- 05Support live and individual backtest modes
Use cases
- 01Launch several OpenAlgo strategies under shared risk caps
- 02Stop strategy processes when portfolio limits are reached
- 03Run separate backtests for portfolio constituents
MCP support
The skill describes a runner that uses OpenAlgo's client and platform operations to monitor positions and manage orders. It does not specify an MCP server or MCP client integration.
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ marketcalls/ openalgo-execution-skills --skill algo-portfolioAfter installing, type/algo-portfolioin Claude Code to confirm it loaded.
Details
From the project READMELaunch a multi-strategy portfolio with global risk caps.
Arguments
$0= path to YAML config. Default:portfolio.yamlin current directory- Pass
--mode backtestor--mode liveafter the config path
If no config exists, generate a starter portfolio.yaml.
Instructions
- Read
algo-expert/rules/portfolio-risk.md. - If the config file doesn't exist, generate this starter:
# Portfolio Runner Configuration
# See algo-expert/rules/portfolio-risk.md for cap explanations
capital: 1000000
portfolio_caps:
portfolio_sl_pct: 0.02 # halt all at -2% capital
portfolio_tp_pct: 0.03 # halt all at +3% capital
daily_loss_pct: 0.015 # daily loss limit
daily_target_pct: 0.025 # daily target
max_concurrent_positions: 5
max_symbol_concentration: 0.30 # max 30% of capital in one symbol
strategies:
# List your generated strategies. The runner spawns each as a subprocess.
- name: ema_sbin
path: strategies/ema_crossover_SBIN/strategy.py
env:
SYMBOL: SBIN
INTERVAL: 5m
- name: rsi_reliance
path: strategies/rsi_RELIANCE/strategy.py
env:
SYMBOL: RELIANCE
INTERVAL: 15m
- Verify each strategy path exists. If not, suggest running
/algo-strategyto create them first. - Generate a runner script
run_portfolio.pyat the project root (or update if exists) that wrapscore/portfolio_runner.py:
"""Portfolio runner entry point."""
import argparse, logging, os, sys
from pathlib import Path
from dotenv import find_dotenv, load_dotenv
# Add core helpers to path
_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
from core.portfolio_runner import PortfolioRunner
logging.basicConfig(level=os.getenv("LOG_LEVEL", "INFO"),
format="%(asctime)s [%(levelname)s] %(name)s - %(message)s",
stream=sys.stdout)
load_dotenv(find_dotenv(usecwd=True))
def make_client():
return api(
api_key=os.getenv("OPENALGO_API_KEY", ""),
host=os.getenv("HOST_SERVER") or os.getenv("OPENALGO_HOST", "http://127.0.0.1:5000"),
)
def main():
p = argparse.ArgumentParser()
p.add_argument("--config", default="portfolio.yaml")
p.add_argument("--mode", choices=["backtest", "live"], default="live")
args = p.parse_args()
runner = PortfolioRunner(args.config, client_factory=make_client, mode=args.mode)
runner.start()
runner.join()
if __name__ == "__main__":
main()
-
Run it:
python run_portfolio.py --config portfolio.yaml --mode live -
Tell the user:
- Each strategy runs in its own subprocess (full isolation)
- SIGTERM is propagated when caps breach OR on Ctrl-C
- The runner monitors aggregate P&L every 15s via
client.positionbook() - On breach:
cancelallorder+closepositionare called platform-wide - Live vs sandbox is decided by OpenAlgo's UI analyzer toggle (same as a single strategy)
Backtest mode
Aggregate-equity backtest of multiple strategies needs custom merging logic (rebalancing weights, cap timing). The default runner does NOT do this in backtest mode - each child runs its own VectorBT backtest independently. To get a true portfolio backtest, see algo-expert/rules/portfolio-risk.md for the merge-equities pattern.
Cap precedence
When multiple caps fire at once, the most restrictive wins. The kill switch fires once per session - re-running the runner resets daily counters at IST midnight.
Telegram alerts on cap breach
To wire Telegram alerts when the portfolio halts, set TELEGRAM_USERNAME in .env and extend core/portfolio_runner.py's stop_all() method. See logging-and-alerts.md.
Avoid
- Do not use icons/emojis
- Do not silently increase the cap when it breaches - that defeats the safety net
- Do not run two
PortfolioRunnerprocesses against the same OpenAlgo instance - they'd both try to flatten on breach and conflict