a763ab0774
- Detect AMD GPUs via ROCm device name in config - Replace single-timestep LSTM in GNN model with leaner post-GNN MLP - Pass edge_attr through AMDGATConv propagate and use ones for self-loops - Fix live trading to sell existing positions on negative signals instead of skipping them entirely - Use per-file try/except in data pipeline and batch SQLite inserts - Import torch directly in backtester instead of dynamic __import__ - Update AMP autocast import for PyTorch 2.0+ compatibility
211 lines
6.7 KiB
Python
211 lines
6.7 KiB
Python
import os
|
|
from datetime import datetime, timedelta
|
|
|
|
import torch
|
|
from dotenv import load_dotenv
|
|
|
|
load_dotenv()
|
|
|
|
|
|
def _check_amd_gpu() -> bool:
|
|
"""Detect AMD GPU via ROCm device name."""
|
|
if not torch.cuda.is_available():
|
|
return False
|
|
try:
|
|
name = torch.cuda.get_device_name(0)
|
|
return any(kw in name for kw in ("AMD", "Radeon", "gfx"))
|
|
except Exception:
|
|
return False
|
|
|
|
|
|
class Config:
|
|
# Project settings
|
|
PROJECT_NAME = "StockGNN_R9700"
|
|
VERSION = "1.0.0"
|
|
|
|
# Data directories
|
|
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
DATA_DIR = os.path.join(BASE_DIR, "data")
|
|
RAW_DATA_DIR = os.path.join(DATA_DIR, "raw")
|
|
PROCESSED_DATA_DIR = os.path.join(DATA_DIR, "processed")
|
|
EXTERNAL_DATA_DIR = os.path.join(DATA_DIR, "external")
|
|
MODEL_DIR = os.path.join(BASE_DIR, "models")
|
|
|
|
# Stock universe settings
|
|
INITIAL_TICKERS = [
|
|
"AAPL",
|
|
"MSFT",
|
|
"GOOGL",
|
|
"AMZN",
|
|
"META",
|
|
"TSLA",
|
|
"NVDA",
|
|
"JPM",
|
|
"V",
|
|
"WMT",
|
|
"PG",
|
|
"DIS",
|
|
"NFLX",
|
|
"ADBE",
|
|
"PYPL",
|
|
"INTC",
|
|
"CSCO",
|
|
"PEP",
|
|
"KO",
|
|
"XOM",
|
|
"BAC",
|
|
"VZ",
|
|
"T",
|
|
"CRM",
|
|
"CMCSA",
|
|
"PFE",
|
|
"NKE",
|
|
"MRK",
|
|
"CVX",
|
|
"HD",
|
|
]
|
|
INDEX_TICKER = "^GSPC" # S&P 500
|
|
DELISTED_TICKERS_FILE = os.path.join(EXTERNAL_DATA_DIR, "delisted_stocks.csv")
|
|
|
|
# Date settings
|
|
START_DATE = "2015-01-01"
|
|
END_DATE = datetime.now().strftime("%Y-%m-%d")
|
|
TRAIN_END_DATE = "2022-12-31"
|
|
VAL_END_DATE = "2023-06-30"
|
|
TEST_END_DATE = END_DATE
|
|
|
|
# AMD GPU settings (Radeon R9700 AI Pro - 32GB)
|
|
DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
|
|
AMD_GPU = _check_amd_gpu()
|
|
GPU_MEMORY_LIMIT = 0.9 # Use 90% of 32GB = 28.8GB
|
|
ROCM_OPT_LEVEL = "O2" # Optimization level for ROCm ('O0', 'O1', 'O2')
|
|
PIN_MEMORY = True # Enable pinned memory for faster data transfer
|
|
MIXED_PRECISION = True # Enable mixed precision training
|
|
PRECISION = "bf16" # 'fp16' or 'bf16' for mixed precision
|
|
|
|
# Model settings
|
|
MODEL_NAME = "stock_gnn_r9700"
|
|
HIDDEN_CHANNELS = 128 # Increased for R9700's compute power
|
|
NUM_HEADS = 16 # Increased number of attention heads
|
|
DROPOUT = 0.3 # Reduced dropout for better GPU utilization
|
|
LEARNING_RATE = 0.0005 # Lower learning rate for stability
|
|
EPOCHS = 200 # More epochs with larger batch sizes
|
|
BATCH_SIZE = 128 # Larger batch size for R9700's memory
|
|
SEQUENCE_LENGTH = 60 # Longer sequences with more memory
|
|
PREDICTION_HORIZON = 10 # Number of steps to predict ahead
|
|
|
|
# Intraday trading settings
|
|
TRADING_FREQUENCY = "5min" # '1min', '5min', '15min', '30min', '1h'
|
|
TRADING_HOURS = {
|
|
"start": "09:30", # Market open (ET)
|
|
"end": "16:00", # Market close (ET)
|
|
}
|
|
PRE_MARKET_HOURS = {
|
|
"start": "04:00", # Pre-market start
|
|
"end": "09:30", # Pre-market end
|
|
}
|
|
AFTER_HOURS = {
|
|
"start": "16:00", # After-hours start
|
|
"end": "20:00", # After-hours end
|
|
}
|
|
MAX_POSITION_HOLD_TIME = "4h" # Maximum time to hold a position
|
|
MIN_POSITION_HOLD_TIME = "10min" # Minimum time to hold a position
|
|
MAX_DAILY_POSITIONS = 50 # Maximum number of positions per day
|
|
MAX_POSITION_SIZE = 0.03 # Maximum % of portfolio per position (3%)
|
|
|
|
# Data pipeline settings
|
|
LOOKBACK_WINDOW = 60 # Days for feature calculation
|
|
REALTIME_FEATURE_WINDOW = 30 # Number of data points for real-time features
|
|
DATA_BUFFER_SIZE = 5000 # Number of data points to keep in memory
|
|
DATA_FLUSH_INTERVAL = 300 # seconds - how often to flush data to database
|
|
|
|
# Alternative data settings (set via .env or environment variables)
|
|
NEWS_API_KEY = os.environ.get("NEWS_API_KEY", "")
|
|
TWITTER_BEARER_TOKEN = os.environ.get("TWITTER_BEARER_TOKEN", "")
|
|
REDDIT_CLIENT_ID = os.environ.get("REDDIT_CLIENT_ID", "")
|
|
REDDIT_CLIENT_SECRET = os.environ.get("REDDIT_CLIENT_SECRET", "")
|
|
NEWS_LOOKBACK_DAYS = 7 # Number of days to look back for news
|
|
SOCIAL_MEDIA_LOOKBACK_DAYS = 3 # Number of days to look back for social media
|
|
|
|
# Feature definitions (referenced by models)
|
|
NEWS_FEATURES = [
|
|
"sentiment",
|
|
"volume",
|
|
"recency",
|
|
"source_reliability",
|
|
"topic_relevance",
|
|
]
|
|
SOCIAL_FEATURES = [
|
|
"twitter_sentiment",
|
|
"twitter_volume",
|
|
"reddit_sentiment",
|
|
"reddit_volume",
|
|
"social_momentum",
|
|
]
|
|
INTRADAY_FEATURES = [
|
|
"return",
|
|
"volatility",
|
|
"momentum",
|
|
"volume_momentum",
|
|
"bid_ask_spread",
|
|
"bid_ask_spread_pct",
|
|
"volume_imbalance",
|
|
"order_flow",
|
|
"vwap_deviation",
|
|
]
|
|
|
|
# Stateful prediction
|
|
STATEFUL_PREDICTION = False
|
|
REALTIME_UPDATE_INTERVAL = 60 # seconds
|
|
|
|
# Backtesting settings
|
|
INITIAL_CAPITAL = 100000
|
|
TRANSACTION_COST = 0.0005 # 0.05% per trade
|
|
SLIPPAGE_MODEL = "volume_curve" # 'volume_curve', 'constant', or 'none'
|
|
SLIPPAGE_RATE = 0.0002 # 0.02% slippage
|
|
|
|
# Live trading settings
|
|
LIVE_DATA_ENABLED = True
|
|
DATA_PROVIDER = "polygon" # 'polygon', 'alphavantage', 'ib', 'tdameritrade'
|
|
POLYGON_API_KEY = os.environ.get("POLYGON_API_KEY", "")
|
|
ALPHA_VANTAGE_API_KEY = os.environ.get("ALPHA_VANTAGE_API_KEY", "")
|
|
IB_HOST = "127.0.0.1"
|
|
IB_PORT = 7497
|
|
IB_CLIENT_ID = 1
|
|
|
|
# WebSocket settings
|
|
WEBSOCKET_RECONNECT_DELAY = 5 # seconds
|
|
WEBSOCKET_MAX_RETRIES = 20
|
|
WEBSOCKET_PING_INTERVAL = 30 # seconds
|
|
|
|
# Data loading settings
|
|
NUM_WORKERS = 8 # Number of data loading workers
|
|
PREFETCH_FACTOR = 4 # Number of batches to prefetch
|
|
|
|
# Online learning settings
|
|
ONLINE_LEARNING = True # Enable online learning
|
|
ONLINE_LEARNING_RATE = 0.0001 # Learning rate for online updates
|
|
ONLINE_LEARNING_INTERVAL = 3600 # seconds - how often to perform online learning
|
|
|
|
# Risk management settings
|
|
MAX_DAILY_LOSS = 0.01 # 1% max daily loss
|
|
MAX_DRAWDOWN = 0.05 # 5% max drawdown
|
|
VOLATILITY_TARGET = 0.15 # Annualized volatility target
|
|
POSITION_SIZING = (
|
|
"volatility_target" # 'volatility_target', 'equal_weight', 'kelly'
|
|
)
|
|
|
|
# Execution settings
|
|
EXECUTION_ALGORITHM = "vwap" # 'vwap', 'twap', 'pov', 'implementation_shortfall'
|
|
EXECUTION_TIME_HORIZON = "5min" # Time to complete execution
|
|
MARKET_IMPACT_MODEL = "kyle" # 'kyle', 'almgren_chriss', or 'none'
|
|
|
|
def __init__(self):
|
|
os.makedirs(self.RAW_DATA_DIR, exist_ok=True)
|
|
os.makedirs(self.PROCESSED_DATA_DIR, exist_ok=True)
|
|
os.makedirs(self.EXTERNAL_DATA_DIR, exist_ok=True)
|
|
os.makedirs(self.MODEL_DIR, exist_ok=True)
|
|
|
|
|
|
config = Config()
|