Multi-Stock Trading Simulation: Diversify Your Portfolio!
Hey guys! Let's dive into an exciting new feature for our trading simulation: multiple stock trading support! This upgrade lets you trade several stocks at the same time, opening up a whole new world of strategies like portfolio diversification, pairs trading, and figuring out which stocks are a steal versus overpriced.
Overview
Currently, our simulation is pretty solid. We've got single-stock trading down with dividends, short-selling, and a detailed order book. Plus, we've got the risk-free rate covered with interest on cash. However, you can't trade multiple different stocks just yet, which is where this awesome upgrade comes in!
Motivation
So, why are we even bothering with multiple stocks? Well, imagine the possibilities! With multiple stock support, we can really dig into some cool research areas:
- Pairs Trading: This lets you play with mean-reversion strategies using stocks that tend to move together.
- Relative Value: You can spot which stocks are undervalued or overvalued compared to their peers.
- Portfolio Diversification: Building portfolios across different stocks can help spread risk.
- Sector Dynamics: Simulate how different sectors like tech and consumer goods interact.
- Contagion: See how a hiccup in one stock can ripple through others.
- Market Making: Provide liquidity across multiple stocks and earn the spread.
- Information Spillovers: Explore how news about one stock affects others in the same industry.
Required Changes
Alright, let's get into the nitty-gritty of what needs to change to make this happen:
1. Core Data Structures
First up, we need to tweak some of our core data structures:
- [ ] Add
stock_idfield toOrderclass (src/market/orders/order.py) - [ ] Add
stock_idfield toTradeclass (src/market/trade.py) - [ ] Update
AgentRepositoryto trackDict[stock_id, shares]positions- Current: Single
sharesfield - New:
positions = {"AAPL": 1000, "MSFT": 500}
- Current: Single
- [ ] Add portfolio-level position tracking (total value, allocations)
2. Market Infrastructure
Next, we need to beef up our market infrastructure:
- [ ] Create
StockContextclass (per-stock version ofSimulationContext)- Each stock has its own: price, fundamental value, dividend params
- [ ] Create
MultiStockContextto manage multipleStockContextinstances - [ ] Build
OrderBookRegistry- one order book per stock - [ ] Update
MatchingEngineto route orders bystock_id- Match AAPL orders separately from MSFT orders
- [ ] Create per-stock
DividendServiceinstances - [ ] Add stock correlation modeling (optional)
3. Scenario Configuration
We'll need to update src/scenarios.py to handle the new multi-stock configurations. Check out this example:
"multi_stock_scenario": {
"STOCKS": {
"TECH_A": {
"INITIAL_PRICE": 100,
"FUNDAMENTAL_PRICE": 95,
"REDEMPTION_VALUE": 95,
"DIVIDEND_PARAMS": {
"base_dividend": 2.0,
"probability": 0.5,
"variation": 0.5
}
},
"TECH_B": {
"INITIAL_PRICE": 50,
"FUNDAMENTAL_PRICE": 55,
"REDEMPTION_VALUE": 55,
"DIVIDEND_PARAMS": {
"base_dividend": 1.0,
"probability": 0.6,
"variation": 0.3
}
}
},
"CORRELATIONS": {
("TECH_A", "TECH_B"): 0.7 # Positively correlated tech stocks
},
"AGENT_PARAMS": {
"INITIAL_CASH": 1000000,
"INITIAL_POSITIONS": {
"TECH_A": 5000,
"TECH_B": 10000
}
}
}
4. Agent System
Our agents need an upgrade too! That means we need to:
- [ ] Update
BaseAgent.decide()to returnList[Order]withstock_id- Agents can now trade multiple stocks per round
- [ ] Rewrite LLM prompt templates for portfolio of stocks:
Your Stock Portfolio:
1. TECH_A
- Price: $100.00, Fundamental: $95.00 (5% overvalued)
- Your Position: 5,000 shares ($500,000 value)
- P/F Ratio: 1.05
2. TECH_B
- Price: $50.00, Fundamental: $55.00 (10% undervalued)
- Your Position: 10,000 shares ($500,000 value)
- P/F Ratio: 0.91
Cash: $200,000
Total Portfolio Value: $1,200,000
Consider:
- Which stock offers better value?
- Should you rebalance between stocks?
- Are there arbitrage opportunities?
- [ ] Implement new deterministic strategies:
- [ ] Pairs Trader: Buy undervalued stock, sell overvalued stock
- [ ] Relative Value Trader: Focus on P/F ratio differences
- [ ] Sector Rotator: Rotate between stocks based on momentum
- [ ] Multi-Stock Market Maker: Provide liquidity in multiple stocks
5. Information Providers
Information is key, so we'll also need to update our information providers:
- [ ] Update
MarketPriceProviderto provide prices for all stocks - [ ] Update
DividendProviderto distinguish which stock pays dividends - [ ] Add
CorrelationProviderfor stock-to-stock relationships (optional) - [ ] Update agent information formatting to show all stocks
6. Position & Trade Services
We'll need services to keep the positions in check. These include
- [ ] Update
PositionCalculatorfor stock-specific position changes - [ ] Update
PositionServicesto handle multi-stock portfolio updates - [ ] Update commitment tracking per stock:
- Cash committed across all stocks
- Shares committed per stock
- [ ] Add portfolio-level valuation (mark-to-market across all stocks)
7. Data Recording & Analysis
Keeping track of everything is essential for analysis, so we'll update the DataRecorder for:
- [ ] Per-stock trade data with
stock_idcolumn - [ ] Per-stock price/volume/fundamental data
- [ ] Portfolio-level metrics:
- Total portfolio value over time
- Stock allocation percentages
- Correlation realized vs expected
- Cross-stock trading flows
- [ ] New visualizations:
- [ ] Portfolio composition (stacked area chart)
- [ ] Relative performance (Stock A vs Stock B)
- [ ] Cross-stock correlation heatmaps
- [ ] Pairs spread plots (price_A/price_B over time)
8. Base Simulation Loop
Finally, the heart of the simulation needs an update. Here's how src/base_sim.py will change:
def run_round(self):
# Collect decisions (agents return orders for multiple stocks)
orders = self.collect_agent_decisions()
# Match each stock's orders independently
results = {}
for stock_id in self.stocks:
stock_orders = [o for o in orders if o.stock_id == stock_id]
results[stock_id] = self.engines[stock_id].match(stock_orders)
# Update each stock's price independently
for stock_id, result in results.items():
self.contexts[stock_id].current_price = result.clearing_price
# (Optional) Apply cross-stock effects (correlation shocks)
self.update_correlation_dynamics()
# Pay dividends for each stock
for stock_id, dividend_service in self.dividend_services.items():
dividend_service.pay_dividends(round_number)
Implementation Strategy
To make this manageable, we'll break it down into phases:
Phase 1: Foundation (2 Stocks)
- Start with just 2 stocks to prove the concept.
- Reuse existing single-stock infrastructure.
- Focus on data structure changes.
Phase 2: Agent Intelligence
- Update LLM prompts for multi-stock portfolio context.
- Implement pairs trading and relative value strategies.
- Add portfolio metrics to decision inputs.
Phase 3: Market Dynamics (Optional)
- Add cross-stock correlations.
- Information spillovers between stocks.
- Sector effects.
Phase 4: Scenarios & Analysis
- Create multi-stock scenario configurations.
- Portfolio analysis tools.
- Pairs trading experiments.
Example Scenarios
Let's think about some cool scenarios we can test out:
Scenario 1: Pairs Trading
- 2 tech stocks with 0.8 correlation.
- One starts overvalued, one undervalued.
- Test if agents exploit mean-reversion.
Scenario 2: Value vs Growth
- "Value" stock: High dividend, low P/F.
- "Growth" stock: Low dividend, high P/F.
- Test agent preferences and allocation.
Scenario 3: Contagion
- Shock one stock's fundamental value.
- Observe spillover effects on other stock.
Design Principles
We want to make sure we're doing this right, so we're sticking to these principles:
- ✅ Backwards Compatibility: Keep single-stock scenarios working
- ✅ Stock-First Design: Focus on equities, not bonds/commodities
- ✅ Incremental Testing: Test with 2 stocks, then scale to N stocks
- ✅ Research Focus: Enable pairs trading, relative value research
Success Criteria
How will we know if we've nailed it? We'll be looking for these things:
- [ ] Can run a scenario with 2+ stocks
- [ ] Agents can submit orders for multiple stocks per round
- [ ] Portfolio value correctly calculated (mark-to-market)
- [ ] Can observe pairs trading behavior
- [ ] At least 2 multi-stock scenarios (pairs trading, value vs growth)
Simplifications vs Multi-Asset
Since all assets are stocks (same class):
- ✅ Same order mechanics (limit/market, short-selling)
- ✅ Same dividend mechanics (just different params per stock)
- ✅ No need for bond-specific features (duration, yield curve)
- ✅ Simpler agent prompts (comparing apples to apples)
Key Files
Keep an eye on these files as we roll this out:
src/market/orders/order.py- Addstock_idfieldsrc/scenarios.py- Multi-stock configurationsrc/agents/LLMs/llm_agent.py- Portfolio decision logicsrc/agents/agent_manager/agent_repository.py- Multi-stock positionssrc/base_sim.py- Main simulation loopsrc/market/state/sim_context.py- Per-stock context
Alright guys, that's the plan! Get ready to level up your trading simulation game!