38 - Python Strategies Hosting

Overview

OpenAlgo provides a cross-platform Python strategy hosting system that allows users to upload, run, schedule, and manage trading strategies. Each strategy runs in a separate process for complete isolation with support for Windows, Linux, and macOS.

Architecture Diagram

┌──────────────────────────────────────────────────────────────────────────────┐
│                    Python Strategy Hosting Architecture                       │
└──────────────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────────────┐
│                          Web Interface (/python)                             │
│                                                                              │
│  ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐       │
│  │    Upload    │ │    Start     │ │   Schedule   │ │    Delete    │       │
│  │   Strategy   │ │   Strategy   │ │   Strategy   │ │   Strategy   │       │
│  └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘       │
│         │                │                │                │                │
└─────────┴────────────────┴────────────────┴────────────────┴────────────────┘


┌─────────────────────────────────────────────────────────────────────────────┐
│                      Strategy Management Layer                               │
│                                                                              │
│  ┌─────────────────────────────────────────────────────────────────────┐   │
│  │  RUNNING_STRATEGIES = {}   # {strategy_id: {'process', 'started'}} │   │
│  │  STRATEGY_CONFIGS = {}     # {strategy_id: config_dict}             │   │
│  │  SCHEDULER (APScheduler)   # Background job scheduler               │   │
│  │  PROCESS_LOCK              # Thread-safe process operations         │   │
│  └─────────────────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────────────────────┐
│                      Process Isolation Layer                                 │
│                                                                              │
│  ┌────────────────┐ ┌────────────────┐ ┌────────────────┐                  │
│  │  Strategy 1    │ │  Strategy 2    │ │  Strategy 3    │  ...              │
│  │  (subprocess)  │ │  (subprocess)  │ │  (subprocess)  │                  │
│  │                │ │                │ │                │                  │
│  │  - Own PID     │ │  - Own PID     │ │  - Own PID     │                  │
│  │  - Own memory  │ │  - Own memory  │ │  - Own memory  │                  │
│  │  - Own stdout  │ │  - Own stdout  │ │  - Own stdout  │                  │
│  │  - Own stderr  │ │  - Own stderr  │ │  - Own stderr  │                  │
│  └────────────────┘ └────────────────┘ └────────────────┘                  │
└─────────────────────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────────────────────┐
│                           File System                                        │
│                                                                              │
│  strategies/                                                                 │
│  ├── scripts/                    # Strategy Python files                    │
│  │   ├── strategy_1.py                                                      │
│  │   ├── strategy_2.py                                                      │
│  │   └── ...                                                                │
│  └── strategy_configs.json       # Persistent configuration                 │
│                                                                              │
│  log/                                                                        │
│  └── strategies/                 # Strategy output logs                     │
│      ├── strategy_1.log                                                     │
│      ├── strategy_2.log                                                     │
│      └── ...                                                                │
└─────────────────────────────────────────────────────────────────────────────┘

Directory Structure

Key Features

Process Isolation

Each strategy runs in a separate subprocess:

Cross-Platform Support

Platform
Support
Notes

Windows

Full

Uses subprocess

Linux

Full

Uses subprocess

macOS

Full

Uses subprocess

Strategy Lifecycle

Scheduling with APScheduler

Scheduler Configuration

Schedule Options

Schedule Type
Description
Example

One-time

Start at specific time

09:15 IST

Interval

Repeat at fixed interval

Every 5 minutes

Cron

Complex scheduling

Weekdays at 09:15

Market Hours

Only during trading

09:15 - 15:30

Market-Aware Scheduling

User Ownership & Security

Strategy Ownership Verification

Security Features

Feature
Implementation

User isolation

Each user sees only their strategies

Path traversal protection

Reject .., /, \ in strategy IDs

Secure filename

werkzeug.utils.secure_filename()

Process isolation

Separate subprocess per strategy

Server-Sent Events (SSE)

Real-time status updates via SSE:

API Endpoints

Endpoint
Method
Description

/python/

GET

List all strategies

/python/upload

POST

Upload new strategy

/python/start/<id>

POST

Start a strategy

/python/stop/<id>

POST

Stop a strategy

/python/schedule/<id>

POST

Schedule a strategy

/python/delete/<id>

DELETE

Delete a strategy

/python/logs/<id>

GET

Get strategy logs

/python/status/<id>

GET

Get strategy status

/python/events

GET

SSE status stream

Configuration Persistence

Operational Guidelines

Best Practices

  1. Keep strategies stateless - Don't rely on global state between runs

  2. Use logging - Write to stdout/stderr for log capture

  3. Handle graceful shutdown - Catch SIGTERM/SIGINT

  4. Use OpenAlgo API - Don't bypass the API layer

Example Strategy Template

Log Monitoring

Resource Configuration

Memory Limits

Each strategy subprocess has a configurable memory limit to prevent runaway strategies from crashing the system:

Container RAM
Recommended Limit
Max Concurrent Strategies

2GB

256MB

5

4GB

512MB

5-8

8GB+

1024MB (default)

10+

Thread Limiting for Docker

When running strategies with numerical libraries (NumPy, SciPy, Numba) in Docker, thread limits prevent RLIMIT_NPROC exhaustion:

Variable
Purpose

OPENBLAS_NUM_THREADS

OpenBLAS thread limit

OMP_NUM_THREADS

OpenMP thread limit

MKL_NUM_THREADS

Intel MKL thread limit

NUMEXPR_NUM_THREADS

NumExpr thread limit

NUMBA_NUM_THREADS

Numba JIT thread limit

For 2GB containers, set all to 1. For 4GB+, use 2. See Docker Configuration for details.

Reference: GitHub Issue #822arrow-up-right

Key Files Reference

File
Purpose

blueprints/python_strategy.py

Strategy hosting blueprint

strategies/scripts/

User strategy files

strategies/strategy_configs.json

Configuration persistence

log/strategies/

Strategy log output

database/market_calendar_db.py

Market hours/holidays

Last updated