Bot API Reference
tradingbot.utils.botclass.Bot(name: str, symbol: Optional[str] = None, interval: str = '1m', period: str = '1d', **kwargs)
Base class for trading bots.
Provides common functionality for data fetching, trading operations, portfolio management, and database interactions.
Data Caching: - Each Bot instance has its own DataService instance with per-instance caching. - For cross-run data reuse (e.g., hyperparameter tuning), data is persisted to the database when saveToDB=True. Subsequent fetches check the database first and only call yfinance if data is missing or stale. - Best practice: Use saveToDB=True for historical backtests to enable efficient data reuse across multiple runs or parameter combinations.
Subclasses should implement either: - decisionFunction(row) -> int: Returns -1 (sell), 0 (hold), or 1 (buy) - makeOneIteration() -> int: Custom iteration logic
Initialize a trading bot.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Unique name for the bot (used for database identification) |
required |
symbol
|
Optional[str]
|
Trading symbol (e.g., "EURUSD=X", "^XAU", "QQQ") Optional for multi-asset bots that override makeOneIteration() |
None
|
interval
|
str
|
Data interval (e.g., "1m", "5m", "1h", "1d") - default: "1m" |
'1m'
|
period
|
str
|
Data period (e.g., "1d", "5d", "1mo", "1y") - default: "1d" |
'1d'
|
**kwargs
|
Arbitrary hyperparameters that will be stored in self.params and can be accessed by subclasses for flexible parameterization |
{}
|
Source code in tradingbot/utils/botclass.py
addPdDFToDb(df: pd.DataFrame) -> None
Add DataFrame rows to database, skipping duplicates.
Only inserts rows with timestamps newer than the latest in database.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
df
|
DataFrame
|
DataFrame with columns: symbol, timestamp, open, high, low, close, volume |
required |
Source code in tradingbot/utils/botclass.py
buy(symbol: str, quantityUSD: float = -1) -> None
Buy a quantity of the specified symbol.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
symbol
|
str
|
Trading symbol to buy |
required |
quantityUSD
|
float
|
Amount in USD to spend (-1 means use all available cash) |
-1
|
Source code in tradingbot/utils/botclass.py
convertToWideFormat(data_long: pd.DataFrame, value_column: str = 'close', fill_method: str = 'both') -> pd.DataFrame
Convert long-format DataFrame to wide format for portfolio optimization.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data_long
|
DataFrame
|
DataFrame in long format with columns: symbol, timestamp, open, high, low, close, volume |
required |
value_column
|
str
|
Column name to use as values (default: "close") |
'close'
|
fill_method
|
str
|
How to handle missing values - "forward", "backward", "both", or None |
'both'
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame with timestamp as index, symbols as columns, and specified value column as values |
Source code in tradingbot/utils/botclass.py
decisionFunction(row: pd.Series) -> int
Decision function that determines trading action based on market data row.
Must be overridden by subclasses (unless using makeOneIteration() instead).
This is the preferred approach for most bots. The base class will: 1. Apply this function to each row in the DataFrame 2. Average the last N decisions (default: 1) 3. Execute trades based on the final decision
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
row
|
Series
|
Pandas Series containing: - Market data: symbol, timestamp, open, high, low, close, volume - Technical indicators: ~150+ indicators (e.g., momentum_rsi, trend_macd, etc.) - Access via: row["indicator_name"] |
required |
Returns:
| Type | Description |
|---|---|
int
|
-1: Sell signal (will sell holdings if any exist) 0: Hold (no action taken) 1: Buy signal (will buy if cash available) |
Example
def decisionFunction(self, row): if row["momentum_rsi"] < 30: return 1 # Oversold, buy elif row["momentum_rsi"] > 70: return -1 # Overbought, sell return 0 # Hold
Source code in tradingbot/utils/botclass.py
getDataFromDB(symbol: str, start_date: Optional[pd.Timestamp] = None, end_date: Optional[pd.Timestamp] = None) -> pd.DataFrame
Load data from database for a symbol.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
symbol
|
str
|
Trading symbol to query |
required |
start_date
|
Optional[Timestamp]
|
Optional start date (timezone-aware UTC) |
None
|
end_date
|
Optional[Timestamp]
|
Optional end date (timezone-aware UTC) |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame with columns: symbol, timestamp, open, high, low, close, volume |
DataFrame
|
Empty DataFrame if no data found |
Source code in tradingbot/utils/botclass.py
getLatestDecision(data: pd.DataFrame, nrMedianLatest: int = 1) -> int
Get the latest trading decision by applying decisionFunction to data.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
DataFrame
|
DataFrame with market data |
required |
nrMedianLatest
|
int
|
Number of latest rows to average (default: 1) |
1
|
Returns:
| Type | Description |
|---|---|
int
|
Averaged decision signal (-1, 0, or 1) |
Source code in tradingbot/utils/botclass.py
getLatestPrice(symbol: str) -> float
Get the latest price for a symbol, using TTL cache and checking DB first.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
symbol
|
str
|
Trading symbol to get price for |
required |
Returns:
| Type | Description |
|---|---|
float
|
Latest price as float |
Raises:
| Type | Description |
|---|---|
ValueError
|
If no price data is available |
Source code in tradingbot/utils/botclass.py
getLatestPricesBatch(symbols: list[str]) -> dict[str, float]
Get latest prices for multiple symbols in a single DB query.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
symbols
|
list[str]
|
List of trading symbols to get prices for |
required |
Returns:
| Type | Description |
|---|---|
dict[str, float]
|
Dictionary mapping symbol to latest price |
Source code in tradingbot/utils/botclass.py
getYFData(symbol: Optional[str] = None, interval: str = '1m', period: str = '1d', saveToDB: bool = False) -> pd.DataFrame
Fetch market data from Yahoo Finance, checking database first.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
symbol
|
Optional[str]
|
Trading symbol (defaults to self.symbol) |
None
|
interval
|
str
|
Data interval (e.g., "1m", "5m", "1h", "1d") |
'1m'
|
period
|
str
|
Data period (e.g., "1d", "5d", "1mo", "1y") |
'1d'
|
saveToDB
|
bool
|
Whether to save fetched data to database |
False
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame with columns: symbol, timestamp, open, high, low, close, volume |
Source code in tradingbot/utils/botclass.py
getYFDataMultiple(symbols: list[str], interval: str = '1d', period: str = '3mo', saveToDB: bool = True) -> pd.DataFrame
Fetch market data for multiple symbols efficiently, checking database first.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
symbols
|
list[str]
|
List of trading symbols to fetch |
required |
interval
|
str
|
Data interval (e.g., "1m", "5m", "1h", "1d") |
'1d'
|
period
|
str
|
Data period (e.g., "1d", "5d", "1mo", "3mo", "1y") |
'3mo'
|
saveToDB
|
bool
|
Whether to save fetched data to database for each symbol |
True
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame with columns: symbol, timestamp, open, high, low, close, volume |
DataFrame
|
Combined data from all symbols in long format |
Source code in tradingbot/utils/botclass.py
getYFDataWithTA(symbol: Optional[str] = None, interval: str = '1m', period: str = '1d', saveToDB: bool = False) -> pd.DataFrame
Fetch market data with technical analysis indicators.
Data fetching strategy: - Checks database first for existing data - Only fetches from yfinance if data is missing or stale - If saveToDB=True, saves fetched data to database for future reuse
Note: For repeated backtests or hyperparameter tuning, set saveToDB=True to enable efficient data reuse across multiple runs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
symbol
|
Optional[str]
|
Trading symbol (defaults to self.symbol) |
None
|
interval
|
str
|
Data interval (e.g., "1m", "5m", "1h", "1d") |
'1m'
|
period
|
str
|
Data period (e.g., "1d", "5d", "1mo", "1y") |
'1d'
|
saveToDB
|
bool
|
Whether to save fetched data to database. Set to True for historical backtests to enable data reuse. |
False
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame with market data and technical analysis features |
Source code in tradingbot/utils/botclass.py
local_backtest(initial_capital: float = 10000.0) -> Dict[str, Any]
Local-only helper: run a backtest with current instance parameters.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
initial_capital
|
float
|
Starting capital for backtest |
10000.0
|
Returns:
| Type | Description |
|---|---|
Dict[str, Any]
|
Backtest results dictionary |
Source code in tradingbot/utils/botclass.py
local_development(param_grid: Optional[Dict[str, List[Any]]] = None, objective: str = 'sharpe_ratio', initial_capital: float = 10000.0, n_jobs: Optional[int] = None) -> Dict[str, Any]
Convenience wrapper for the typical local development workflow:
1) Optimize hyperparameters for this bot's class 2) Backtest a bot instance constructed with the best parameters
Does NOT modify init defaults; you still paste them manually.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
param_grid
|
Optional[Dict[str, List[Any]]]
|
Optional parameter grid to use. If None, uses self.param_grid or class attribute. |
None
|
objective
|
str
|
Metric to maximize ("sharpe_ratio" or "yearly_return") |
'sharpe_ratio'
|
initial_capital
|
float
|
Starting capital for backtests |
10000.0
|
n_jobs
|
Optional[int]
|
Number of parallel jobs (None = auto-detect) |
None
|
Returns:
| Type | Description |
|---|---|
Dict[str, Any]
|
Optimization results dictionary with 'best_params' and performance metrics |
Example
bot = MyBot() results = bot.local_development()
Prints best parameters in copy-paste format
Then backtests with those parameters
Copy the printed parameters into init defaults
Source code in tradingbot/utils/botclass.py
local_optimize(param_grid: Optional[Dict[str, List[Any]]] = None, objective: str = 'sharpe_ratio', initial_capital: float = 10000.0, n_jobs: Optional[int] = None) -> Dict[str, Any]
Local-only helper: run hyperparameter optimization for this bot's class.
Uses either the provided param_grid or self.param_grid (if defined as class attribute). Prints the best combination in a format easy to copy-paste into init defaults.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
param_grid
|
Optional[Dict[str, List[Any]]]
|
Optional parameter grid to use. If None, uses self.param_grid or class attribute. |
None
|
objective
|
str
|
Metric to maximize ("sharpe_ratio" or "yearly_return") |
'sharpe_ratio'
|
initial_capital
|
float
|
Starting capital for backtests |
10000.0
|
n_jobs
|
Optional[int]
|
Number of parallel jobs (None = auto-detect) |
None
|
Returns:
| Type | Description |
|---|---|
Dict[str, Any]
|
Full optimization results dictionary |
Raises:
| Type | Description |
|---|---|
ValueError
|
If no param_grid is defined |
Source code in tradingbot/utils/botclass.py
makeOneIteration() -> int
Execute one iteration of the trading bot.
Default implementation: 1. Fetches data with technical indicators 2. Gets decision by applying decisionFunction() to data 3. Executes buy/sell based on decision
When to override: - Multi-asset bots (must override if self.symbol is None) - External data sources (e.g., Fear & Greed Index API) - Portfolio optimization strategies - Custom data processing beyond row-by-row logic
When NOT to override: - Simple single-asset strategies (just implement decisionFunction() instead) - Strategies that only need different timeframes (set interval/period in init)
Returns:
| Type | Description |
|---|---|
int
|
-1: Sold 0: No action 1: Bought |
Raises:
| Type | Description |
|---|---|
NotImplementedError
|
If self.symbol is None (multi-asset bot) and method not overridden |
Source code in tradingbot/utils/botclass.py
rebalancePortfolio(targetPortfolio: dict[str, float], onlyOver50USD: bool = False) -> None
Rebalance portfolio to match target weights.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
targetPortfolio
|
dict[str, float]
|
Dictionary mapping symbols to target weights (e.g., {"VWCE": 0.8, "GLD": 0.1, "USD": 0.1}) Weights must sum to 1.0 (100%) |
required |
onlyOver50USD
|
bool
|
If True, filter out assets with target value <= $50 and redistribute weights equally among remaining assets (default: False) |
False
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If weights don't sum to 1.0 (within tolerance) |
Source code in tradingbot/utils/botclass.py
run() -> None
Execute one iteration of the bot and log results.
Catches exceptions and logs them to the database before re-raising.
Source code in tradingbot/utils/botclass.py
sell(symbol: str, quantityUSD: float = -1) -> None
Sell a quantity of the specified symbol.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
symbol
|
str
|
Trading symbol to sell |
required |
quantityUSD
|
float
|
Amount in USD to sell (-1 means sell all holdings) |
-1
|