Most algo trading tutorials skip straight to "here's a strategy, backtest it, profit." What they leave out is the plumbing: how do you run multiple strategies simultaneously, compare them fairly, and actually learn something useful before going live?
This is a walkthrough of how TradeSight is structured โ the key modules, the tournament system, and how Alpaca's free paper trading API ties it together. No fluff, just the architecture.
The obvious answer is "don't lose real money testing." But there's a subtler reason: backtesting and live trading behave differently in ways that bite you.
Backtesting assumes perfect execution โ your order fills at the close price, no slippage, no market impact. In reality, your order either isn't filled or fills worse. Alpaca's paper trading API mirrors live market conditions: it enforces market hours, uses real-time prices, and simulates realistic fills. The gap between your backtest and your paper results tells you more than either one alone.
The project is organized around three layers:
paper_trader.py is the runtime hub. It connects to Alpaca, spawns the strategy threads, and manages position tracking. The strategies directory is where the actual logic lives โ each one extends a common base class that enforces a consistent interface.
The tournament runs every night after market close. It backtests all 9 strategies against 30 days of historical data (pulled via yfinance), scores them on a composite metric, and flags the top performer for next-day live paper trading.
The scoring formula weights four factors:
# tournament/scorer.py (simplified)
def composite_score(backtest_result):
sharpe = backtest_result['sharpe_ratio']
drawdown = backtest_result['max_drawdown']
win_rate = backtest_result['win_rate']
profit_factor = backtest_result['profit_factor']
# Hard disqualification
if drawdown > 0.15:
return -1
# Weighted composite (weights tuned over 3 months of paper results)
score = (sharpe * 0.40) + (win_rate * 0.30) + (profit_factor * 0.20) + ((1 - drawdown) * 0.10)
return round(score, 4)
The tournament runs roughly 45 minutes on an M4 Mac Mini, backtesting across 12 tickers per strategy. The winner gets flagged in the database; paper_trader.py picks it up at market open.
Alpaca's paper trading environment is free and genuinely useful. You get a real API, real-time market data, and a simulated $100k portfolio that resets on demand. The alpaca-py SDK handles the heavy lifting:
# paper_trader.py (simplified connection)
from alpaca.trading.client import TradingClient
from alpaca.trading.requests import MarketOrderRequest
from alpaca.trading.enums import OrderSide, TimeInForce
client = TradingClient(
api_key=os.getenv('ALPACA_API_KEY'),
secret_key=os.getenv('ALPACA_SECRET_KEY'),
paper=True # paper=False for live โ the only change needed
)
def place_order(symbol, qty, side):
order = MarketOrderRequest(
symbol=symbol,
qty=qty,
side=OrderSide.BUY if side == 'buy' else OrderSide.SELL,
time_in_force=TimeInForce.DAY
)
return client.submit_order(order)
The paper=True flag is the only difference between paper and live mode. When you're ready to go live, you swap in your live API keys and flip that flag. Everything else stays identical.
TradeSight is intentionally minimal โ it's a lab, not a finished product. The architecture is designed to be extended:
BaseStrategy, implement generate_signal(), drop it in strategies/. The tournament picks it up automatically on the next run.The entire codebase is ~2,400 lines of Python. There's no external framework dependency beyond alpaca-py and yfinance. You can read it in an afternoon.
Clone the repo, get a free Alpaca paper trading account (takes 2 minutes), and you're running:
git clone https://github.com/rmbell09-lang/tradesight
cd tradesight
pip install -r requirements.txt
# Add to .env:
# ALPACA_API_KEY=your_key
# ALPACA_SECRET_KEY=your_secret
python run_paper_trader.py
The overnight tournament runs automatically via cron. First results show up the next morning in the dashboard.