fix: query previous day's holdings instead of current day

**Problem:**
Subsequent trading days were not retrieving starting holdings correctly.
The API showed empty starting_position and final_position even after
executing multiple buy trades.

**Root Cause:**
get_current_position_from_db() used `date <= ?` which returned the
CURRENT day's trading_day record instead of the PREVIOUS day's ending.
Since holdings are written at END of trading day, querying the current
day's record would return incomplete/empty holdings.

**Timeline on Day 1 (2025-10-02):**
1. Start: Create trading_day with empty holdings
2. Trade: Execute 8 buy trades (recorded in actions table)
3. End: Call get_current_position_from_db(date='2025-10-02')
   - Query: `date <= 2025-10-02` returns TODAY's record
   - Holdings: EMPTY (not written yet)
   - Saves: Empty holdings to database 

**Solution:**
Changed query to use `date < ?` to retrieve PREVIOUS day's ending
position, which becomes the current day's starting position.

**Impact:**
- Day 1: Correctly saves ending holdings after trades
- Day 2+: Correctly retrieves previous day's ending as starting position
- Holdings now persist between trading days as expected

**Tests Added:**
- test_get_position_retrieves_previous_day_not_current: Verifies query
  returns previous day when multiple days exist
- Updated existing tests to align with new behavior

Fixes holdings persistence bug identified in API response showing
empty starting_position/final_position despite successful trades.
This commit is contained in:
2025-11-04 23:29:30 -05:00
parent 05620facc2
commit aa16480158
2 changed files with 116 additions and 18 deletions

View File

@@ -28,16 +28,17 @@ def get_current_position_from_db(
initial_cash: float = 10000.0
) -> Tuple[Dict[str, float], int]:
"""
Get current position from database (new schema).
Get starting position for current trading day from database (new schema).
Queries most recent trading_day record for this job+model up to date.
Returns ending holdings and cash from that day.
Queries most recent trading_day record BEFORE the given date (previous day's ending).
Returns ending holdings and cash from that previous day, which becomes the
starting position for the current day.
Args:
job_id: Job UUID
model: Model signature
date: Current trading date
initial_cash: Initial cash if no prior data
date: Current trading date (will query for date < this)
initial_cash: Initial cash if no prior data (first trading day)
Returns:
(position_dict, action_count) where:
@@ -49,11 +50,11 @@ def get_current_position_from_db(
cursor = conn.cursor()
try:
# Query most recent trading_day up to date
# Query most recent trading_day BEFORE current date (previous day's ending position)
cursor.execute("""
SELECT id, ending_cash
FROM trading_days
WHERE job_id = ? AND model = ? AND date <= ?
WHERE job_id = ? AND model = ? AND date < ?
ORDER BY date DESC
LIMIT 1
""", (job_id, model, date))