EvalItUp exposes a local HTTP API on port 8080. Send a JSON POST from any Python script — no proprietary SDK, no complex wrapper, just standard HTTP.
Why Python for Automated Trading?
Python is the preferred language for algorithmic trading thanks to its powerful libraries (pandas, numpy, scikit-learn, TensorFlow). With EvalItUp, your Python scripts can execute directly on your Rithmic prop firm accounts.
From your ML model to Rithmic execution in a single line of code: requests.post()Why Use Python with EvalItUp?
Traditional trading platforms don't integrate easily with Python. EvalItUp offers a simple HTTP API that works with any script.
Traditional Integrations
- Complex proprietary SDKs with limited documentation
- C++ or Java dependencies difficult to install
- High latency via bridges or cloud APIs
- No native multi-account support
- Constant maintenance during platform updates
With EvalItUp
- Simple HTTP POST — works with requests, httpx, aiohttp
- No dependencies: pip install requests and you're ready
- < 5ms local latency — ideal for HFT
- Dispatch to unlimited accounts with a single request
- Stable API — no breaking changes
Complete API Reference
Endpoint
application/jsonhttp://127.0.0.1:8080/signal/{workflow_id}Max size: 64 KB
Required Fields
- schema_version
- "1.0" or "1.1" — Schema version (1.1 adds action, order_id, parent_order_id)
- signal_id
- Unique signal identifier (UUID recommended)
- workflow_id
- Target pool/workflow name (case-sensitive)
- instrument
- Object {exchange, symbol} — e.g., {"exchange": "CME", "symbol": "ESU6"}
- side
- Direction: BUY, SELL, LONG, SHORT
- qty
- Number of contracts (positive integer)
Optional Fields
- order_type
- MARKET (default), LIMIT, STOP, STOP_LIMIT
- limit_price
- Limit price (required if LIMIT or STOP_LIMIT)
- trigger_price
- Trigger price (required if STOP or STOP_LIMIT)
- bracket
- Object {take_profit, stop_loss} for bracket orders
- open_close
- OPEN or CLOSE — indicates if order opens or closes a position
HTTP Responses
{"status": "accepted", "signal_id": "abc-123"}{"error": "Missing required field: qty"}{"error": "Workflow not found: xyz"}Python Code Examples
Copy-paste these examples into your scripts. All use the requests library (pip install requests).
Basic Signal
Sends a simple market order
import requests
import uuid
def send_signal(pool, symbol, side, qty):
url = f"http://127.0.0.1:8080/signal/{pool}"
signal = {
"schema_version": "1.0",
"signal_id": str(uuid.uuid4()),
"workflow_id": pool,
"instrument": {
"exchange": "CME",
"symbol": symbol
},
"side": side,
"qty": qty
}
response = requests.post(url, json=signal, timeout=5)
return response.json()
# Example
result = send_signal("my-pool", "MESU6", "BUY", 2)
print(result)Signal with Take Profit and Stop Loss
Generates 3 linked orders automatically (entry + TP + SL)
import requests
import uuid
def send_bracket_order(pool, symbol, side, qty, tp_price, sl_price):
url = f"http://127.0.0.1:8080/signal/{pool}"
signal = {
"schema_version": "1.0",
"signal_id": str(uuid.uuid4()),
"workflow_id": pool,
"instrument": {
"exchange": "CME",
"symbol": symbol
},
"side": side,
"qty": qty,
"bracket": {
"take_profit": {
"limit_price": tp_price
},
"stop_loss": {
"trigger_price": sl_price
}
}
}
response = requests.post(url, json=signal, timeout=5)
return response.json()
# Example: Buy 1 MES with TP +20 points and SL -10 points
entry_price = 5070.00
result = send_bracket_order(
pool="scalping-mes",
symbol="MESU6",
side="BUY",
qty=1,
tp_price=entry_price + 20,
sl_price=entry_price - 10
)
print(result)Limit Order
Buys only if price reaches your limit
import requests
import uuid
def send_limit_order(pool, symbol, side, qty, limit_price):
url = f"http://127.0.0.1:8080/signal/{pool}"
signal = {
"schema_version": "1.0",
"signal_id": str(uuid.uuid4()),
"workflow_id": pool,
"instrument": {
"exchange": "CME",
"symbol": symbol
},
"side": side,
"qty": qty,
"order_type": "LIMIT",
"limit_price": limit_price
}
response = requests.post(url, json=signal, timeout=5)
return response.json()
# Example: Buy 1 ES at 5050 or less
result = send_limit_order("swing-es", "ESU6", "BUY", 1, 5050.00)
print(result)Complete EvalItUp Class
Reusable Python wrapper for all your trading projects
import requests
import uuid
from typing import Optional, Literal
class EvalItUpClient:
def __init__(self, base_url: str = "http://127.0.0.1:8080"):
self.base_url = base_url
self.session = requests.Session()
self.session.headers.update({"Content-Type": "application/json"})
def send_signal(
self,
pool: str,
symbol: str,
side: Literal["BUY", "SELL"],
qty: int,
exchange: str = "CME",
order_type: str = "MARKET",
limit_price: Optional[float] = None,
trigger_price: Optional[float] = None,
tp_price: Optional[float] = None,
sl_price: Optional[float] = None
) -> dict:
signal = {
"schema_version": "1.0",
"signal_id": str(uuid.uuid4()),
"workflow_id": pool,
"instrument": {
"exchange": exchange,
"symbol": symbol
},
"side": side,
"qty": qty
}
if order_type != "MARKET":
signal["order_type"] = order_type
if limit_price:
signal["limit_price"] = limit_price
if trigger_price:
signal["trigger_price"] = trigger_price
if tp_price or sl_price:
signal["bracket"] = {}
if tp_price:
signal["bracket"]["take_profit"] = {"limit_price": tp_price}
if sl_price:
signal["bracket"]["stop_loss"] = {"trigger_price": sl_price}
url = f"{self.base_url}/signal/{pool}"
response = self.session.post(url, json=signal, timeout=5)
return response.json()
def close_position(self, pool: str, symbol: str, side: Literal["BUY", "SELL"], qty: int) -> dict:
signal = {
"schema_version": "1.0",
"signal_id": str(uuid.uuid4()),
"workflow_id": pool,
"instrument": {"exchange": "CME", "symbol": symbol},
"side": side,
"qty": qty,
"open_close": "CLOSE"
}
url = f"{self.base_url}/signal/{pool}"
return self.session.post(url, json=signal, timeout=5).json()
# Usage
client = EvalItUpClient()
client.send_signal("my-pool", "MESU6", "BUY", 2)
client.send_signal("my-pool", "MESU6", "BUY", 1, tp_price=5100, sl_price=5050)
client.close_position("my-pool", "MESU6", "SELL", 2)Async Version (asyncio + aiohttp)
For high-performance bots with parallel processing
import aiohttp
import asyncio
import uuid
async def send_signal_async(pool, symbol, side, qty):
url = f"http://127.0.0.1:8080/signal/{pool}"
signal = {
"schema_version": "1.0",
"signal_id": str(uuid.uuid4()),
"workflow_id": pool,
"instrument": {"exchange": "CME", "symbol": symbol},
"side": side,
"qty": qty
}
async with aiohttp.ClientSession() as session:
async with session.post(url, json=signal) as response:
return await response.json()
# Send multiple signals in parallel
async def main():
tasks = [
send_signal_async("pool-1", "MESU6", "BUY", 1),
send_signal_async("pool-2", "MNQU6", "BUY", 1),
send_signal_async("pool-3", "MESU6", "SELL", 1),
]
results = await asyncio.gather(*tasks)
for r in results:
print(r)
asyncio.run(main())Python Use Cases
Machine Learning Trading
Connect your scikit-learn, TensorFlow or PyTorch models. When your model predicts an opportunity, send the signal to EvalItUp.
if model.predict(features) > threshold: send_signal('ml-pool', 'MESU6', 'BUY', 1)From Backtest to Live
Use the same code for backtest and live. Simply change the execution handler to call the EvalItUp API.
Backtest mode: simulated_fill() | Live mode: send_signal()Real-Time Data Analysis
Combine pandas and numpy with real-time data feeds. Detect patterns and execute immediately.
WebSocket market data → pandas analysis → signal if condition metMulti-Strategy Orchestration
Run multiple Python strategies in parallel, each targeting a different pool.
Thread 1: scalping → pool-scalp | Thread 2: swing → pool-swingScheduled Trading
Use schedule or APScheduler for time-based executions.
schedule.every().day.at('09:30').do(execute_open_strategy)Python Framework Integrations
Backtrader
Popular backtesting framework. Create a custom broker that calls the EvalItUp API.
Zipline / Zipline-Reloaded
Used by Quantopian. Implement a custom execution handler.
VectorBT
Ultra-fast vectorized backtesting. Ideal for prototyping.
Jupyter Notebooks
Prototype your strategies interactively and execute from the notebook.
Best Practices
Error Handling
Always wrap your API calls in try/except
try:
result = send_signal(...)
if result.get('status') != 'accepted':
logger.error(f"Signal rejected: {result}")
except requests.Timeout:
logger.error("EvalItUp API timeout")
except requests.ConnectionError:
logger.error("EvalItUp not reachable")Logging
Log each signal with its signal_id for debugging
Simulation Testing
Always test on simulation accounts before going live
Rate Limiting
Avoid sending too many signals too quickly
Tutorial: First Python Signal
Follow this guide to send your first signal from a Python script.
1. Install the requests library
The standard HTTP library for Python
pip install requests2. Launch EvalItUp
Open EvalItUp and connect to your Rithmic accounts. The local API starts automatically on http://127.0.0.1:8080
3. Create a Test Pool
In EvalItUp, create a pool named 'python-test' and add a simulation account to it.
4. Send a Test Signal
Run this code. You should see status 200 and the signal in EvalItUp → Activity.
import requests
response = requests.post(
"http://127.0.0.1:8080/signal/python-test",
json={
"schema_version": "1.0",
"signal_id": "test-001",
"workflow_id": "python-test",
"instrument": {"exchange": "CME", "symbol": "MESU6"},
"side": "BUY",
"qty": 1
}
)
print(response.status_code) # 200
print(response.json()) # {"status": "accepted", ...}5. Verify in EvalItUp
Open the Activity tab in EvalItUp. You'll see your 'test-001' signal and the orders sent to pool accounts.
Python Trade Copier FAQ
Does EvalItUp need to be open for the API to work?
Yes. The HTTP API is hosted by the EvalItUp application. If the app is closed, requests will fail with ConnectionError.
Can I use the API from a remote server?
By default, the API listens on 127.0.0.1 (localhost). For remote access, use an SSH tunnel or configure a secure reverse proxy.
What is the API latency?
< 5ms locally. The time includes validation and sending to Rithmic accounts. Rithmic execution adds 1-5ms.
Can I send multiple signals in parallel?
Yes. Use asyncio with aiohttp, or ThreadPoolExecutor. Each signal is processed independently.
Does the API support authentication?
Optionally. Configure a Bearer token in EvalItUp → Settings → API, then add the Authorization: Bearer YOUR_TOKEN header.
How do I debug if my signals aren't executing?
1) Check HTTP code (200=OK, 400=JSON error, 404=pool not found). 2) Check EvalItUp logs. 3) Verify workflow_id = exact pool name.
Can I use this API with other languages?
Yes. It's a standard HTTP API. It works with curl, JavaScript, C#, Go, Rust, or any language capable of sending HTTP POSTs.
How do I integrate with Backtrader or Zipline backtest?
Create a custom broker/execution handler that calls send_signal() instead of simulating fills. Keep the same strategy logic.