docs: update changelog and schema docs for position tracking fixes

Document the critical bug fixes for position tracking:
- Cash reset to initial value each day
- Positions lost over weekends
- Incorrect profit calculations treating trades as losses

Update database schema documentation to explain the corrected
profit calculation logic that compares to start-of-day portfolio
value instead of previous day's final value.
This commit is contained in:
2025-11-03 21:34:34 -05:00
parent 9be14a1602
commit 84320ab8a5
2 changed files with 43 additions and 0 deletions

View File

@@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
### Fixed
- **Critical:** Fixed position tracking bugs causing cash reset and positions lost over weekends
- Removed redundant `ModelDayExecutor._write_results_to_db()` that created corrupt records with cash=0 and holdings=[]
- Fixed profit calculation to compare against start-of-day portfolio value instead of previous day's final value
- Positions now correctly carry over between trading days and across weekends
- Profit/loss calculations now accurately reflect trading gains/losses without treating trades as losses
### Changed
- Position tracking now exclusively handled by trade tools (`buy()`, `sell()`) and `add_no_trade_record_to_db()`
- Daily profit calculation compares to start-of-day (action_id=0) portfolio value for accurate P&L tracking
## [0.3.0] - 2025-11-03 ## [0.3.0] - 2025-11-03
### Added - Development & Testing Features ### Added - Development & Testing Features

View File

@@ -64,6 +64,38 @@ CREATE TABLE positions (
); );
``` ```
**Column Descriptions:**
| Column | Type | Description |
|--------|------|-------------|
| id | INTEGER | Primary key, auto-incremented |
| job_id | TEXT | Foreign key to jobs table |
| date | TEXT | Trading date (YYYY-MM-DD) |
| model | TEXT | Model signature/identifier |
| action_id | INTEGER | Sequential action ID for the day (0 = start-of-day baseline) |
| action_type | TEXT | Type of action: 'no_trade', 'buy', or 'sell' |
| symbol | TEXT | Stock symbol (null for no_trade) |
| amount | INTEGER | Number of shares traded (null for no_trade) |
| price | REAL | Price per share (null for no_trade) |
| cash | REAL | Cash balance after action |
| portfolio_value | REAL | Total portfolio value (cash + holdings value) |
| daily_profit | REAL | **Daily profit/loss compared to start-of-day portfolio value (action_id=0).** Calculated as: `current_portfolio_value - start_of_day_portfolio_value`. This shows the actual gain/loss from price movements and trading decisions, not affected by merely buying/selling stocks. |
| daily_return_pct | REAL | **Daily return percentage compared to start-of-day portfolio value.** Calculated as: `(daily_profit / start_of_day_portfolio_value) * 100` |
| created_at | TEXT | ISO 8601 timestamp with 'Z' suffix |
**Important Notes:**
- **Position tracking flow:** Positions are written by trade tools (`buy()`, `sell()` in `agent_tools/tool_trade.py`) and no-trade records (`add_no_trade_record_to_db()` in `tools/price_tools.py`). Each trade creates a new position record.
- **Action ID sequence:**
- `action_id=0`: Start-of-day position (created by `ModelDayExecutor._initialize_starting_position()` on first day only)
- `action_id=1+`: Each trade or no-trade action increments the action_id
- **Profit calculation:** Daily profit is calculated by comparing current portfolio value to the **start-of-day** portfolio value (action_id=0 for the current date). This ensures that:
- Buying stocks doesn't show as a loss (cash ↓, stock value ↑ equally)
- Selling stocks doesn't show as a gain (cash ↑, stock value ↓ equally)
- Only actual price movements and strategic trading show as profit/loss
### holdings ### holdings
Portfolio holdings breakdown per position. Portfolio holdings breakdown per position.