mirror of
https://github.com/Xe138/AI-Trader.git
synced 2026-04-08 11:47:24 -04:00
docs: update API reference and database schema for new results endpoint
This commit is contained in:
331
API_REFERENCE.md
331
API_REFERENCE.md
@@ -343,7 +343,7 @@ Poll every 10-30 seconds until `status` is `completed`, `partial`, or `failed`.
|
|||||||
|
|
||||||
### GET /results
|
### GET /results
|
||||||
|
|
||||||
Query simulation results with optional filters.
|
Get trading results grouped by day with daily P&L metrics and AI reasoning.
|
||||||
|
|
||||||
**Query Parameters:**
|
**Query Parameters:**
|
||||||
|
|
||||||
@@ -352,112 +352,315 @@ Query simulation results with optional filters.
|
|||||||
| `job_id` | string | No | Filter by job UUID |
|
| `job_id` | string | No | Filter by job UUID |
|
||||||
| `date` | string | No | Filter by trading date (YYYY-MM-DD) |
|
| `date` | string | No | Filter by trading date (YYYY-MM-DD) |
|
||||||
| `model` | string | No | Filter by model signature |
|
| `model` | string | No | Filter by model signature |
|
||||||
|
| `reasoning` | string | No | Include AI reasoning: `none` (default), `summary`, or `full` |
|
||||||
|
|
||||||
**Response (200 OK):**
|
**Response (200 OK) - Default (no reasoning):**
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
"count": 2,
|
||||||
"results": [
|
"results": [
|
||||||
{
|
{
|
||||||
"id": 1,
|
"date": "2025-01-15",
|
||||||
"job_id": "550e8400-e29b-41d4-a716-446655440000",
|
|
||||||
"date": "2025-01-16",
|
|
||||||
"model": "gpt-4",
|
"model": "gpt-4",
|
||||||
"action_id": 1,
|
"job_id": "550e8400-e29b-41d4-a716-446655440000",
|
||||||
"action_type": "buy",
|
"starting_position": {
|
||||||
"symbol": "AAPL",
|
"holdings": [],
|
||||||
"amount": 10,
|
"cash": 10000.0,
|
||||||
"price": 250.50,
|
"portfolio_value": 10000.0
|
||||||
"cash": 7495.00,
|
},
|
||||||
"portfolio_value": 10000.00,
|
"daily_metrics": {
|
||||||
"daily_profit": 0.00,
|
"profit": 0.0,
|
||||||
"daily_return_pct": 0.00,
|
"return_pct": 0.0,
|
||||||
"created_at": "2025-01-16T10:05:23Z",
|
"days_since_last_trading": 0
|
||||||
"holdings": [
|
},
|
||||||
{"symbol": "AAPL", "quantity": 10},
|
"trades": [
|
||||||
{"symbol": "CASH", "quantity": 7495.00}
|
{
|
||||||
]
|
"action_type": "buy",
|
||||||
|
"symbol": "AAPL",
|
||||||
|
"quantity": 10,
|
||||||
|
"price": 150.0,
|
||||||
|
"created_at": "2025-01-15T14:30:00Z"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"final_position": {
|
||||||
|
"holdings": [
|
||||||
|
{"symbol": "AAPL", "quantity": 10}
|
||||||
|
],
|
||||||
|
"cash": 8500.0,
|
||||||
|
"portfolio_value": 10000.0
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"total_actions": 1,
|
||||||
|
"session_duration_seconds": 45.2,
|
||||||
|
"completed_at": "2025-01-15T14:31:00Z"
|
||||||
|
},
|
||||||
|
"reasoning": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 2,
|
|
||||||
"job_id": "550e8400-e29b-41d4-a716-446655440000",
|
|
||||||
"date": "2025-01-16",
|
"date": "2025-01-16",
|
||||||
"model": "gpt-4",
|
"model": "gpt-4",
|
||||||
"action_id": 2,
|
"job_id": "550e8400-e29b-41d4-a716-446655440000",
|
||||||
"action_type": "buy",
|
"starting_position": {
|
||||||
"symbol": "MSFT",
|
"holdings": [
|
||||||
"amount": 5,
|
{"symbol": "AAPL", "quantity": 10}
|
||||||
"price": 380.20,
|
],
|
||||||
"cash": 5594.00,
|
"cash": 8500.0,
|
||||||
"portfolio_value": 10105.00,
|
"portfolio_value": 10100.0
|
||||||
"daily_profit": 105.00,
|
},
|
||||||
"daily_return_pct": 1.05,
|
"daily_metrics": {
|
||||||
"created_at": "2025-01-16T10:05:23Z",
|
"profit": 100.0,
|
||||||
"holdings": [
|
"return_pct": 1.0,
|
||||||
{"symbol": "AAPL", "quantity": 10},
|
"days_since_last_trading": 1
|
||||||
{"symbol": "MSFT", "quantity": 5},
|
},
|
||||||
{"symbol": "CASH", "quantity": 5594.00}
|
"trades": [
|
||||||
|
{
|
||||||
|
"action_type": "buy",
|
||||||
|
"symbol": "MSFT",
|
||||||
|
"quantity": 5,
|
||||||
|
"price": 200.0,
|
||||||
|
"created_at": "2025-01-16T14:30:00Z"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"final_position": {
|
||||||
|
"holdings": [
|
||||||
|
{"symbol": "AAPL", "quantity": 10},
|
||||||
|
{"symbol": "MSFT", "quantity": 5}
|
||||||
|
],
|
||||||
|
"cash": 7500.0,
|
||||||
|
"portfolio_value": 10100.0
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"total_actions": 1,
|
||||||
|
"session_duration_seconds": 52.1,
|
||||||
|
"completed_at": "2025-01-16T14:31:00Z"
|
||||||
|
},
|
||||||
|
"reasoning": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Response (200 OK) - With Summary Reasoning:**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"count": 1,
|
||||||
|
"results": [
|
||||||
|
{
|
||||||
|
"date": "2025-01-15",
|
||||||
|
"model": "gpt-4",
|
||||||
|
"job_id": "550e8400-e29b-41d4-a716-446655440000",
|
||||||
|
"starting_position": {
|
||||||
|
"holdings": [],
|
||||||
|
"cash": 10000.0,
|
||||||
|
"portfolio_value": 10000.0
|
||||||
|
},
|
||||||
|
"daily_metrics": {
|
||||||
|
"profit": 0.0,
|
||||||
|
"return_pct": 0.0,
|
||||||
|
"days_since_last_trading": 0
|
||||||
|
},
|
||||||
|
"trades": [
|
||||||
|
{
|
||||||
|
"action_type": "buy",
|
||||||
|
"symbol": "AAPL",
|
||||||
|
"quantity": 10,
|
||||||
|
"price": 150.0,
|
||||||
|
"created_at": "2025-01-15T14:30:00Z"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"final_position": {
|
||||||
|
"holdings": [
|
||||||
|
{"symbol": "AAPL", "quantity": 10}
|
||||||
|
],
|
||||||
|
"cash": 8500.0,
|
||||||
|
"portfolio_value": 10000.0
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"total_actions": 1,
|
||||||
|
"session_duration_seconds": 45.2,
|
||||||
|
"completed_at": "2025-01-15T14:31:00Z"
|
||||||
|
},
|
||||||
|
"reasoning": "Analyzed AAPL earnings report showing strong Q4 results. Bought 10 shares at $150 based on positive revenue guidance and expanding margins."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Response (200 OK) - With Full Reasoning:**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"count": 1,
|
||||||
|
"results": [
|
||||||
|
{
|
||||||
|
"date": "2025-01-15",
|
||||||
|
"model": "gpt-4",
|
||||||
|
"job_id": "550e8400-e29b-41d4-a716-446655440000",
|
||||||
|
"starting_position": {
|
||||||
|
"holdings": [],
|
||||||
|
"cash": 10000.0,
|
||||||
|
"portfolio_value": 10000.0
|
||||||
|
},
|
||||||
|
"daily_metrics": {
|
||||||
|
"profit": 0.0,
|
||||||
|
"return_pct": 0.0,
|
||||||
|
"days_since_last_trading": 0
|
||||||
|
},
|
||||||
|
"trades": [
|
||||||
|
{
|
||||||
|
"action_type": "buy",
|
||||||
|
"symbol": "AAPL",
|
||||||
|
"quantity": 10,
|
||||||
|
"price": 150.0,
|
||||||
|
"created_at": "2025-01-15T14:30:00Z"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"final_position": {
|
||||||
|
"holdings": [
|
||||||
|
{"symbol": "AAPL", "quantity": 10}
|
||||||
|
],
|
||||||
|
"cash": 8500.0,
|
||||||
|
"portfolio_value": 10000.0
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"total_actions": 1,
|
||||||
|
"session_duration_seconds": 45.2,
|
||||||
|
"completed_at": "2025-01-15T14:31:00Z"
|
||||||
|
},
|
||||||
|
"reasoning": [
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": "You are a trading agent. Current date: 2025-01-15..."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "assistant",
|
||||||
|
"content": "I'll analyze market conditions for AAPL..."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "tool",
|
||||||
|
"name": "search",
|
||||||
|
"content": "AAPL Q4 earnings beat expectations..."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "assistant",
|
||||||
|
"content": "Based on positive earnings, I'll buy AAPL..."
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
"count": 2
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
**Response Fields:**
|
**Response Fields:**
|
||||||
|
|
||||||
|
**Top-level:**
|
||||||
| Field | Type | Description |
|
| Field | Type | Description |
|
||||||
|-------|------|-------------|
|
|-------|------|-------------|
|
||||||
| `results` | array[object] | Array of position records |
|
| `count` | integer | Number of trading days returned |
|
||||||
| `count` | integer | Number of results returned |
|
| `results` | array[object] | Array of day-level trading results |
|
||||||
|
|
||||||
**Position Record Fields:**
|
|
||||||
|
|
||||||
|
**Day-level fields:**
|
||||||
| Field | Type | Description |
|
| Field | Type | Description |
|
||||||
|-------|------|-------------|
|
|-------|------|-------------|
|
||||||
| `id` | integer | Unique position record ID |
|
|
||||||
| `job_id` | string | Job UUID this belongs to |
|
|
||||||
| `date` | string | Trading date (YYYY-MM-DD) |
|
| `date` | string | Trading date (YYYY-MM-DD) |
|
||||||
| `model` | string | Model signature |
|
| `model` | string | Model signature |
|
||||||
| `action_id` | integer | Action sequence number (1, 2, 3...) for this model-day |
|
| `job_id` | string | Simulation job UUID |
|
||||||
| `action_type` | string | Action taken: `buy`, `sell`, or `hold` |
|
| `starting_position` | object | Portfolio state at start of day |
|
||||||
| `symbol` | string | Stock symbol traded (or null for `hold`) |
|
| `daily_metrics` | object | Daily performance metrics |
|
||||||
| `amount` | integer | Quantity traded (or null for `hold`) |
|
| `trades` | array[object] | All trades executed during the day |
|
||||||
| `price` | float | Price per share (or null for `hold`) |
|
| `final_position` | object | Portfolio state at end of day |
|
||||||
| `cash` | float | Cash balance after this action |
|
| `metadata` | object | Session metadata |
|
||||||
| `portfolio_value` | float | Total portfolio value (cash + holdings) |
|
| `reasoning` | null\|string\|array | AI reasoning (based on `reasoning` parameter) |
|
||||||
| `daily_profit` | float | Profit/loss for this trading day |
|
|
||||||
| `daily_return_pct` | float | Return percentage for this day |
|
|
||||||
| `created_at` | string | ISO 8601 timestamp when recorded |
|
|
||||||
| `holdings` | array[object] | Current holdings after this action |
|
|
||||||
|
|
||||||
**Holdings Object:**
|
|
||||||
|
|
||||||
|
**starting_position fields:**
|
||||||
| Field | Type | Description |
|
| Field | Type | Description |
|
||||||
|-------|------|-------------|
|
|-------|------|-------------|
|
||||||
| `symbol` | string | Stock symbol or "CASH" |
|
| `holdings` | array[object] | Stock positions at start of day (from previous day's ending) |
|
||||||
| `quantity` | float | Shares owned (or cash amount) |
|
| `cash` | float | Cash balance at start of day |
|
||||||
|
| `portfolio_value` | float | Total portfolio value at start (cash + holdings valued at current prices) |
|
||||||
|
|
||||||
|
**daily_metrics fields:**
|
||||||
|
| Field | Type | Description |
|
||||||
|
|-------|------|-------------|
|
||||||
|
| `profit` | float | Dollar amount gained/lost from previous close (portfolio appreciation/depreciation) |
|
||||||
|
| `return_pct` | float | Percentage return from previous close |
|
||||||
|
| `days_since_last_trading` | integer | Number of calendar days since last trading day (1=normal, 3=weekend, 0=first day) |
|
||||||
|
|
||||||
|
**trades fields:**
|
||||||
|
| Field | Type | Description |
|
||||||
|
|-------|------|-------------|
|
||||||
|
| `action_type` | string | Trade type: `buy`, `sell`, or `no_trade` |
|
||||||
|
| `symbol` | string\|null | Stock symbol (null for `no_trade`) |
|
||||||
|
| `quantity` | integer\|null | Number of shares (null for `no_trade`) |
|
||||||
|
| `price` | float\|null | Execution price per share (null for `no_trade`) |
|
||||||
|
| `created_at` | string | ISO 8601 timestamp of trade execution |
|
||||||
|
|
||||||
|
**final_position fields:**
|
||||||
|
| Field | Type | Description |
|
||||||
|
|-------|------|-------------|
|
||||||
|
| `holdings` | array[object] | Stock positions at end of day |
|
||||||
|
| `cash` | float | Cash balance at end of day |
|
||||||
|
| `portfolio_value` | float | Total portfolio value at end (cash + holdings valued at closing prices) |
|
||||||
|
|
||||||
|
**metadata fields:**
|
||||||
|
| Field | Type | Description |
|
||||||
|
|-------|------|-------------|
|
||||||
|
| `total_actions` | integer | Number of trades executed during the day |
|
||||||
|
| `session_duration_seconds` | float\|null | AI session duration in seconds |
|
||||||
|
| `completed_at` | string\|null | ISO 8601 timestamp of session completion |
|
||||||
|
|
||||||
|
**holdings object:**
|
||||||
|
| Field | Type | Description |
|
||||||
|
|-------|------|-------------|
|
||||||
|
| `symbol` | string | Stock symbol |
|
||||||
|
| `quantity` | integer | Number of shares held |
|
||||||
|
|
||||||
|
**reasoning field:**
|
||||||
|
- `null` when `reasoning=none` (default) - no reasoning included
|
||||||
|
- `string` when `reasoning=summary` - AI-generated 2-3 sentence summary of trading strategy
|
||||||
|
- `array` when `reasoning=full` - Complete conversation log with all messages, tool calls, and responses
|
||||||
|
|
||||||
|
**Daily P&L Calculation:**
|
||||||
|
|
||||||
|
Daily profit/loss is calculated by valuing the previous day's ending holdings at current day's opening prices:
|
||||||
|
|
||||||
|
1. **First trading day**: `daily_profit = 0`, `daily_return_pct = 0` (no previous holdings to appreciate/depreciate)
|
||||||
|
2. **Subsequent days**:
|
||||||
|
- Value yesterday's ending holdings at today's opening prices
|
||||||
|
- `daily_profit = today_portfolio_value - yesterday_portfolio_value`
|
||||||
|
- `daily_return_pct = (daily_profit / yesterday_portfolio_value) * 100`
|
||||||
|
|
||||||
|
This accurately captures portfolio appreciation from price movements, not just trading decisions.
|
||||||
|
|
||||||
|
**Weekend Gap Handling:**
|
||||||
|
|
||||||
|
The system correctly handles multi-day gaps (weekends, holidays):
|
||||||
|
- `days_since_last_trading` shows actual calendar days elapsed (e.g., 3 for Monday following Friday)
|
||||||
|
- Daily P&L reflects cumulative price changes over the gap period
|
||||||
|
- Holdings chain remains consistent (Monday starts with Friday's ending positions)
|
||||||
|
|
||||||
**Examples:**
|
**Examples:**
|
||||||
|
|
||||||
All results for a specific job:
|
All results for a specific job (no reasoning):
|
||||||
```bash
|
```bash
|
||||||
curl "http://localhost:8080/results?job_id=550e8400-e29b-41d4-a716-446655440000"
|
curl "http://localhost:8080/results?job_id=550e8400-e29b-41d4-a716-446655440000"
|
||||||
```
|
```
|
||||||
|
|
||||||
Results for a specific date:
|
Results for a specific date with summary reasoning:
|
||||||
```bash
|
```bash
|
||||||
curl "http://localhost:8080/results?date=2025-01-16"
|
curl "http://localhost:8080/results?date=2025-01-16&reasoning=summary"
|
||||||
```
|
```
|
||||||
|
|
||||||
Results for a specific model:
|
Results for a specific model with full reasoning:
|
||||||
```bash
|
```bash
|
||||||
curl "http://localhost:8080/results?model=gpt-4"
|
curl "http://localhost:8080/results?model=gpt-4&reasoning=full"
|
||||||
```
|
```
|
||||||
|
|
||||||
Combine filters:
|
Combine filters:
|
||||||
```bash
|
```bash
|
||||||
curl "http://localhost:8080/results?job_id=550e8400-e29b-41d4-a716-446655440000&date=2025-01-16&model=gpt-4"
|
curl "http://localhost:8080/results?job_id=550e8400-e29b-41d4-a716-446655440000&date=2025-01-16&model=gpt-4&reasoning=summary"
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -42,26 +42,45 @@ CREATE TABLE job_details (
|
|||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
### positions
|
### trading_days
|
||||||
Trading position records with P&L.
|
|
||||||
|
Core table for each model-day execution with daily P&L metrics.
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
CREATE TABLE positions (
|
CREATE TABLE trading_days (
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
job_id TEXT,
|
job_id TEXT NOT NULL,
|
||||||
date TEXT,
|
model TEXT NOT NULL,
|
||||||
model TEXT,
|
date TEXT NOT NULL,
|
||||||
action_id INTEGER,
|
|
||||||
action_type TEXT,
|
-- Starting position (cash only, holdings from previous day)
|
||||||
symbol TEXT,
|
starting_cash REAL NOT NULL,
|
||||||
amount INTEGER,
|
starting_portfolio_value REAL NOT NULL,
|
||||||
price REAL,
|
|
||||||
cash REAL,
|
-- Daily performance metrics
|
||||||
portfolio_value REAL,
|
daily_profit REAL NOT NULL,
|
||||||
daily_profit REAL,
|
daily_return_pct REAL NOT NULL,
|
||||||
daily_return_pct REAL,
|
|
||||||
created_at TEXT
|
-- Ending state (cash only, holdings in separate table)
|
||||||
|
ending_cash REAL NOT NULL,
|
||||||
|
ending_portfolio_value REAL NOT NULL,
|
||||||
|
|
||||||
|
-- Reasoning
|
||||||
|
reasoning_summary TEXT,
|
||||||
|
reasoning_full TEXT,
|
||||||
|
|
||||||
|
-- Metadata
|
||||||
|
total_actions INTEGER DEFAULT 0,
|
||||||
|
session_duration_seconds REAL,
|
||||||
|
days_since_last_trading INTEGER DEFAULT 1,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
completed_at TIMESTAMP,
|
||||||
|
|
||||||
|
UNIQUE(job_id, model, date),
|
||||||
|
FOREIGN KEY (job_id) REFERENCES jobs(job_id)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE INDEX idx_trading_days_lookup ON trading_days(job_id, model, date);
|
||||||
```
|
```
|
||||||
|
|
||||||
**Column Descriptions:**
|
**Column Descriptions:**
|
||||||
@@ -70,45 +89,123 @@ CREATE TABLE positions (
|
|||||||
|--------|------|-------------|
|
|--------|------|-------------|
|
||||||
| id | INTEGER | Primary key, auto-incremented |
|
| id | INTEGER | Primary key, auto-incremented |
|
||||||
| job_id | TEXT | Foreign key to jobs table |
|
| job_id | TEXT | Foreign key to jobs table |
|
||||||
| date | TEXT | Trading date (YYYY-MM-DD) |
|
|
||||||
| model | TEXT | Model signature/identifier |
|
| model | TEXT | Model signature/identifier |
|
||||||
| action_id | INTEGER | Sequential action ID for the day (0 = start-of-day baseline) |
|
| date | TEXT | Trading date (YYYY-MM-DD) |
|
||||||
| action_type | TEXT | Type of action: 'no_trade', 'buy', or 'sell' |
|
| starting_cash | REAL | Cash balance at start of day |
|
||||||
| symbol | TEXT | Stock symbol (null for no_trade) |
|
| starting_portfolio_value | REAL | Total portfolio value at start (includes holdings valued at current prices) |
|
||||||
| amount | INTEGER | Number of shares traded (null for no_trade) |
|
| daily_profit | REAL | Dollar P&L from previous close (portfolio appreciation/depreciation) |
|
||||||
| price | REAL | Price per share (null for no_trade) |
|
| daily_return_pct | REAL | Percentage return from previous close |
|
||||||
| cash | REAL | Cash balance after action |
|
| ending_cash | REAL | Cash balance at end of day |
|
||||||
| portfolio_value | REAL | Total portfolio value (cash + holdings value) |
|
| ending_portfolio_value | REAL | Total portfolio value at end |
|
||||||
| 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. |
|
| reasoning_summary | TEXT | AI-generated 2-3 sentence summary of trading strategy |
|
||||||
| daily_return_pct | REAL | **Daily return percentage compared to start-of-day portfolio value.** Calculated as: `(daily_profit / start_of_day_portfolio_value) * 100` |
|
| reasoning_full | TEXT | JSON array of complete conversation log |
|
||||||
| created_at | TEXT | ISO 8601 timestamp with 'Z' suffix |
|
| total_actions | INTEGER | Number of trades executed during the day |
|
||||||
|
| session_duration_seconds | REAL | AI session duration in seconds |
|
||||||
|
| days_since_last_trading | INTEGER | Days since previous trading day (1=normal, 3=weekend, 0=first day) |
|
||||||
|
| created_at | TIMESTAMP | Record creation timestamp |
|
||||||
|
| completed_at | TIMESTAMP | Session completion timestamp |
|
||||||
|
|
||||||
**Important Notes:**
|
**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.
|
- **Day-centric structure:** Each row represents one complete trading day for one model
|
||||||
|
- **First trading day:** `daily_profit = 0`, `daily_return_pct = 0`, `days_since_last_trading = 0`
|
||||||
|
- **Subsequent days:** Daily P&L calculated by valuing previous day's holdings at current prices
|
||||||
|
- **Weekend gaps:** System handles multi-day gaps automatically (e.g., Monday following Friday shows `days_since_last_trading = 3`)
|
||||||
|
- **Starting holdings:** Derived from previous day's ending holdings (not stored in this table, see `holdings` table)
|
||||||
|
- **Unique constraint:** One record per (job_id, model, date) combination
|
||||||
|
|
||||||
- **Action ID sequence:**
|
**Daily P&L Calculation:**
|
||||||
- `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:
|
Daily profit accurately reflects portfolio appreciation from price movements:
|
||||||
- Buying stocks doesn't show as a loss (cash ↓, stock value ↑ equally)
|
|
||||||
- Selling stocks doesn't show as a gain (cash ↑, stock value ↓ equally)
|
1. Get previous day's ending holdings and cash
|
||||||
- Only actual price movements and strategic trading show as profit/loss
|
2. Value those holdings at current day's opening prices
|
||||||
|
3. `daily_profit = current_value - previous_value`
|
||||||
|
4. `daily_return_pct = (daily_profit / previous_value) * 100`
|
||||||
|
|
||||||
|
This ensures buying/selling stocks doesn't affect P&L - only price changes do.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### holdings
|
### holdings
|
||||||
Portfolio holdings breakdown per position.
|
|
||||||
|
Portfolio holdings snapshots (ending positions only).
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
CREATE TABLE holdings (
|
CREATE TABLE holdings (
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
position_id INTEGER,
|
trading_day_id INTEGER NOT NULL,
|
||||||
symbol TEXT,
|
symbol TEXT NOT NULL,
|
||||||
quantity REAL,
|
quantity INTEGER NOT NULL,
|
||||||
FOREIGN KEY (position_id) REFERENCES positions(id) ON DELETE CASCADE
|
|
||||||
|
FOREIGN KEY (trading_day_id) REFERENCES trading_days(id) ON DELETE CASCADE,
|
||||||
|
UNIQUE(trading_day_id, symbol)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE INDEX idx_holdings_day ON holdings(trading_day_id);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Column Descriptions:**
|
||||||
|
|
||||||
|
| Column | Type | Description |
|
||||||
|
|--------|------|-------------|
|
||||||
|
| id | INTEGER | Primary key, auto-incremented |
|
||||||
|
| trading_day_id | INTEGER | Foreign key to trading_days table |
|
||||||
|
| symbol | TEXT | Stock symbol |
|
||||||
|
| quantity | INTEGER | Number of shares held at end of day |
|
||||||
|
|
||||||
|
**Important Notes:**
|
||||||
|
|
||||||
|
- **Ending positions only:** This table stores only the final holdings at end of day
|
||||||
|
- **Starting positions:** Derived by querying holdings for previous day's trading_day_id
|
||||||
|
- **Cascade deletion:** Holdings are automatically deleted when parent trading_day is deleted
|
||||||
|
- **Unique constraint:** One row per (trading_day_id, symbol) combination
|
||||||
|
- **No cash:** Cash is stored directly in trading_days table (`ending_cash`)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### actions
|
||||||
|
|
||||||
|
Trade execution ledger.
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE TABLE actions (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
trading_day_id INTEGER NOT NULL,
|
||||||
|
|
||||||
|
action_type TEXT NOT NULL,
|
||||||
|
symbol TEXT,
|
||||||
|
quantity INTEGER,
|
||||||
|
price REAL,
|
||||||
|
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
|
||||||
|
FOREIGN KEY (trading_day_id) REFERENCES trading_days(id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX idx_actions_day ON actions(trading_day_id);
|
||||||
|
```
|
||||||
|
|
||||||
|
**Column Descriptions:**
|
||||||
|
|
||||||
|
| Column | Type | Description |
|
||||||
|
|--------|------|-------------|
|
||||||
|
| id | INTEGER | Primary key, auto-incremented |
|
||||||
|
| trading_day_id | INTEGER | Foreign key to trading_days table |
|
||||||
|
| action_type | TEXT | Trade type: 'buy', 'sell', or 'no_trade' |
|
||||||
|
| symbol | TEXT | Stock symbol (NULL for no_trade) |
|
||||||
|
| quantity | INTEGER | Number of shares traded (NULL for no_trade) |
|
||||||
|
| price | REAL | Execution price per share (NULL for no_trade) |
|
||||||
|
| created_at | TIMESTAMP | Timestamp of trade execution |
|
||||||
|
|
||||||
|
**Important Notes:**
|
||||||
|
|
||||||
|
- **Trade ledger:** Sequential log of all trades executed during a trading day
|
||||||
|
- **No_trade actions:** Recorded when agent decides not to trade
|
||||||
|
- **Cascade deletion:** Actions are automatically deleted when parent trading_day is deleted
|
||||||
|
- **Execution order:** Use `created_at` to determine trade execution sequence
|
||||||
|
- **Price snapshot:** Records actual execution price at time of trade
|
||||||
|
|
||||||
### price_data
|
### price_data
|
||||||
Cached historical price data.
|
Cached historical price data.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user