Bot Class System
[!WARNING] DISCLAIMER: This software is for educational and research purposes only. Trading involves significant risk of loss. Use of this framework for live trading is strictly at your own risk.
The Bot class is the foundation of the trading bot system. All bots inherit from it and implement trading strategies.
Implementation Approaches
1a. Simple (Recommended): Single-ticker decisionFunction(row)
When to use: Your strategy can be expressed as logic on a single data row with technical indicators, for one symbol.
How it works:
- Base class fetches data for self.symbol (or self.tickers for multi-asset bots)
- Applies your function to each row
- Averages the last N decisions
- Executes trades automatically
- Fully backtestable via local_backtest() / local_optimize()
Example:
class MyBot(Bot):
def __init__(self):
super().__init__("MyBot", symbol="QQQ", interval="1d", period="1y")
def decisionFunction(self, row):
if row["momentum_rsi"] < 30:
return 1 # Buy
elif row["momentum_rsi"] > 70:
return -1 # Sell
return 0 # Hold
1b. Multi-ticker decisionFunction(row) — equal-weight
When to use: Same row-by-row logic applied across a basket of tickers with equal-weight sizing.
How it works:
- Pass tickers=["SPY", "QQQ", "GLD"] to __init__ instead of symbol=
- decisionFunction is called once per ticker per bar (unchanged signature)
- Buy signal: top up that ticker toward total_value / N
- Sell signal: liquidate that ticker's position
- Live trading: makeOneIteration() routes to _run_multi_ticker_iteration() automatically
- Backtesting: backtest_bot() inner-joins all ticker DataFrames on timestamp and simulates equal-weight
Example:
class MyMultiBot(Bot):
def __init__(self):
super().__init__("MyMultiBot", tickers=["SPY", "QQQ", "GLD"],
interval="1d", period="1y")
def decisionFunction(self, row):
if row["momentum_rsi"] < 30:
return 1
elif row["momentum_rsi"] > 70:
return -1
return 0
2. Medium Complexity: Override makeOneIteration()
When to use: - External APIs (e.g., Fear & Greed Index) - Custom data processing - Different timeframe handling
Example: See feargreedbot.py
3. Complex: Portfolio Optimization
When to use: - Multi-asset strategies - Portfolio rebalancing - Complex optimization algorithms
Example: See sharpeportfoliooptweekly.py
Bot Lifecycle
1. Bot.__init__(name, symbol, interval="1m", period="1d")
├── Creates/retrieves bot from database
├── Initializes portfolio with {"USD": 10000} if new
├── Sets up symbol and data cache
└── Stores interval and period for data fetching
2. Bot.run()
├── Calls makeOneIteration()
├── Executes buy/sell based on decision
└── Logs result to database (RunLog)
3. Bot.makeOneIteration() [default implementation]
├── Fetches data: getYFDataWithTA(saveToDB=True, ...)
├── Gets decision: getLatestDecision(data)
└── Executes trade if decision != 0
Key Methods
Data Fetching
# Raw market data
data = bot.getYFData(interval="1m", period="1d", saveToDB=True)
# With technical indicators
data = bot.getYFDataWithTA(interval="1m", period="1d", saveToDB=True)
Trading Operations
# Buy with all cash
bot.buy(symbol="QQQ")
# Buy specific amount
bot.buy(symbol="QQQ", quantityUSD=1000)
# Sell all holdings
bot.sell(symbol="QQQ")
# Rebalance portfolio
bot.rebalancePortfolio({"QQQ": 0.8, "GLD": 0.1, "USD": 0.1})
Portfolio Access
Data Caching
- Instance cache:
self.datacaches last fetched DataFrame (for single-ticker). For multi-ticker bots,self.datasis a dictionary caching DataFrames keyed by ticker. - Database persistence: Set
saveToDB=Truefor cross-run data reuse - Automatic freshness check: Stale data (>10 minutes) is refetched
Next Steps
- Bot API Reference - Complete method documentation
- Creating a Bot - Step-by-step guide