289 lines
9.7 KiB
Markdown
289 lines
9.7 KiB
Markdown
# Trade Plan Calculation - Data Flow & Sources
|
||
|
||
## Overview
|
||
The trade plan is automatically generated for every options flow signal with a rocket score >= 3. It calculates entry prices, stop losses, profit targets, and risk/reward ratios based on real-time price data.
|
||
|
||
## Entry Point
|
||
**File:** `backend/src/routes/optionsFlow.js` (line 228-233)
|
||
|
||
```javascript
|
||
if (rocketScore >= 3) {
|
||
const tradePlan = generateTradePlan(enrichedRow);
|
||
enrichedRow.tradePlan = tradePlan;
|
||
enrichedRow.tradePlanDisplay = formatTradePlanDisplay(tradePlan);
|
||
}
|
||
```
|
||
|
||
## Data Sources
|
||
|
||
### 1. **Current Price** (Primary Reference)
|
||
**Sources (in priority order):**
|
||
- **`flow.yahooPriceData.currentPrice`** - **REAL-TIME from Yahoo Finance API** ⭐ (PRIMARY)
|
||
- `flow.spot_num` - Spot price from flow data (fallback)
|
||
- `flow.u_close` - Close price at signal time (from database, may be stale)
|
||
- `flow.last_px` - Last price (fallback)
|
||
- `flow.Price` - Fallback price field
|
||
|
||
**Yahoo Finance API:** `https://query1.finance.yahoo.com/v8/finance/chart/{symbol}?interval=1d&range=5d`
|
||
- Returns real-time `regularMarketPrice` or `previousClose`
|
||
- **This is the PRIMARY source for current price** (not database)
|
||
|
||
### 2. **VWAP (Volume Weighted Average Price)**
|
||
**Sources:**
|
||
- `flow.vwap_at_signal` - VWAP calculated at signal time (from Python service)
|
||
- `flow.vwap_lb` - VWAP from SQL query
|
||
- `flow.vwap` - Fallback
|
||
|
||
**Calculation:**
|
||
- Sum of (price × volume) from RTH open to signal time / Sum of volume
|
||
- **Note:** VWAP may still come from database/Python service, but entry prices use Yahoo Finance current price
|
||
|
||
### 3. **RTH Open (Regular Trading Hours Open)**
|
||
**Sources (in priority order):**
|
||
- **`flow.yahooPriceData.open`** - **REAL-TIME from Yahoo Finance API** ⭐ (PRIMARY)
|
||
- `flow.rth_open` - From database (fallback, may be stale)
|
||
- Falls back to current price if unavailable
|
||
|
||
**Yahoo Finance API:** Returns `regularMarketOpen` for today
|
||
|
||
### 4. **Opening Range (OR High/Low)**
|
||
**Sources (in priority order):**
|
||
- **`flow.yahooPriceData.high` / `flow.yahooPriceData.low`** - **REAL-TIME from Yahoo Finance API** ⭐ (PRIMARY)
|
||
- Uses today's high/low as OR levels (more accurate than stale database data)
|
||
- `flow.or_high` / `flow.or_low` - From database (fallback, may be stale)
|
||
- Calculated fallback: `currentPrice * 1.01` (high) or `currentPrice * 0.99` (low)
|
||
|
||
**Yahoo Finance API:** Returns `regularMarketDayHigh` and `regularMarketDayLow` for today
|
||
- **Validation:** Only used if within 10% of current price (to avoid stale data)
|
||
|
||
### 5. **Prior High**
|
||
**Sources (in priority order):**
|
||
- **`flow.yahooPriceData.volumeHistory[1].high`** - **REAL-TIME from Yahoo Finance API** ⭐ (PRIMARY)
|
||
- Gets yesterday's high from volumeHistory (last 5 days data)
|
||
- `flow.prior_high` - From database (fallback, may be stale)
|
||
- `flow.priorHigh` - Alternative field name
|
||
- **Fallback:** `currentPrice * 1.02` (2% above current)
|
||
|
||
**Yahoo Finance API:** Returns volumeHistory with last 5 days including high/low/close
|
||
- **Validation:** Only used if above current price and within 10% above
|
||
|
||
### 6. **Prior Close**
|
||
**Sources (in priority order):**
|
||
- **`flow.yahooPriceData.previousClose`** - **REAL-TIME from Yahoo Finance API** ⭐ (PRIMARY)
|
||
- `flow.prior_close` or `flow.priorClose` - From database (fallback, may be stale)
|
||
|
||
**Yahoo Finance API:** Returns `previousClose` for previous trading day
|
||
|
||
### 7. **Strike Price**
|
||
**Sources:**
|
||
- `flow.strike_num` - Strike price from options flow
|
||
- `flow.Strike` - Alternative field name
|
||
- **Validation:** Only used for T3 target if within 20% of current price
|
||
|
||
## Calculation Flow
|
||
|
||
### Step 1: Determine Signal (BUY/SELL/WAIT)
|
||
**Function:** `determineSignal(flowData)`
|
||
- Based on badges (🟢/🔴, 💎, ⭐, 💰, ⚡)
|
||
- Checks tape alignment
|
||
- Checks rocket score
|
||
|
||
### Step 2: Generate Entry Strategy
|
||
**Function:** `generateEntryStrategy(flowData, signal)`
|
||
|
||
#### For BUY Signals:
|
||
- **Primary Entry:** VWAP (if available) OR current price
|
||
- **Aggressive Entry:** OR high (if reasonable) OR current price * 1.005
|
||
- **Conditional Triggers:**
|
||
- VWAP reclaim (if price < VWAP)
|
||
- Prior high break (if price < prior high)
|
||
- OR breakout (if price < OR high)
|
||
|
||
#### For SELL Signals:
|
||
- **Primary Entry:** VWAP (if available) OR current price
|
||
- **Aggressive Entry:** OR low (if reasonable) OR current price * 0.995
|
||
- **Conditional Triggers:**
|
||
- VWAP rejection (if price > VWAP)
|
||
- OR breakdown (if price > OR low)
|
||
|
||
#### For WAIT Signals:
|
||
- **Primary Entry:** `null` (no entry yet)
|
||
- **Conditional Triggers:**
|
||
- Price breaks prior high (if within 10% above current)
|
||
- OR breakout (if within 5% above current)
|
||
- VWAP reclaim (if within 5% of current)
|
||
- Tape alignment turns positive
|
||
- Flow resumes (if flow is dead/stale)
|
||
|
||
### Step 3: Calculate Stop Loss
|
||
**Function:** `calculateStopLoss(flow, entryPrice)`
|
||
|
||
**Reference Price:**
|
||
- Uses `entryPrice` if available (for BUY/SELL)
|
||
- Uses `currentPrice` if no entry (for WAIT signals)
|
||
|
||
#### For BULL/BUY Signals:
|
||
- **Tight Stop:** `referencePrice * 0.985` (-1.5%)
|
||
- **Wide Stop:**
|
||
- OR low (if within 5% of reference price) OR
|
||
- `referencePrice * 0.975` (-2.5%)
|
||
|
||
#### For BEAR/SELL Signals:
|
||
- **Tight Stop:** `referencePrice * 1.015` (+1.5%)
|
||
- **Wide Stop:**
|
||
- OR high (if within 5% of reference price) OR
|
||
- `referencePrice * 1.025` (+2.5%)
|
||
|
||
### Step 4: Calculate Profit Targets
|
||
**Function:** `calculateTargets(flow, entryPrice, signal)`
|
||
|
||
**Reference Price:**
|
||
- Uses `entryPrice` if available
|
||
- Uses `currentPrice` if no entry (for WAIT signals)
|
||
|
||
#### For BUY/BULL Signals:
|
||
- **T1:** `referencePrice * 1.015` (+1.5%) - Take 50%
|
||
- **T2:** `referencePrice * 1.025` (+2.5%) - Take 30%
|
||
- **T3:**
|
||
- Strike price (if within 20% above reference) OR
|
||
- `referencePrice * 1.04` (+4%) - Runner 20%
|
||
|
||
#### For SELL/BEAR Signals:
|
||
- **T1:** `referencePrice * 0.985` (-1.5%) - Take 50%
|
||
- **T2:** `referencePrice * 0.975` (-2.5%) - Take 30%
|
||
- **T3:**
|
||
- Strike price (if within 20% below reference) OR
|
||
- `referencePrice * 0.96` (-4%) - Runner 20%
|
||
|
||
### Step 5: Calculate Risk/Reward
|
||
**Function:** `calculateRiskReward(entry, stop, target)`
|
||
|
||
**Formula:**
|
||
- Risk = `|stop - entry| / entry * 100`
|
||
- Reward = `|target - entry| / entry * 100`
|
||
- Ratio = `reward / risk`
|
||
|
||
### Step 6: Calculate Readiness (WAIT signals only)
|
||
**Function:** `calculateReadiness(plan)`
|
||
|
||
**Scoring:**
|
||
- Confidence * 0.6 (60% weight)
|
||
- Entry strategy exists: +15 points
|
||
- Stop loss exists: +10 points
|
||
- Targets exist: +10 points
|
||
- Reasoning exists: +5 points
|
||
- **Max:** 100%
|
||
|
||
## Key Validations
|
||
|
||
### Price Level Validation
|
||
All price levels are validated against current price to avoid stale data:
|
||
|
||
1. **OR High/Low:** Only used if within 10% of current price
|
||
2. **Prior High:** Only used if above current and within 10% above
|
||
3. **VWAP:** Only used if within 5% of current price
|
||
4. **Strike Price:** Only used for T3 if within 20% of current price
|
||
|
||
### Fallback Logic
|
||
If any price data is missing or stale:
|
||
- Uses current price as base
|
||
- Calculates percentage-based levels (e.g., +1.5%, -2.5%)
|
||
- Never uses unreasonable/stale data
|
||
|
||
## Example Calculation
|
||
|
||
**Given:**
|
||
- Current Price: $131.81
|
||
- VWAP: $130.50
|
||
- OR High: $132.00
|
||
- OR Low: $130.00
|
||
- Strike: $155.00 (too far, ignored)
|
||
- Signal: WAIT (BULL direction)
|
||
|
||
**Entry Strategy:**
|
||
- Primary: `null` (WAIT signal)
|
||
- Conditional Triggers:
|
||
- VWAP reclaim at $130.50 (if price < VWAP)
|
||
- OR breakout at $132.00 (if price < OR high)
|
||
|
||
**Stop Loss (using current price $131.81):**
|
||
- Tight: $131.81 * 0.985 = $129.83 (-1.5%)
|
||
- Wide: $130.00 (OR low, within 5%)
|
||
|
||
**Targets (using current price $131.81):**
|
||
- T1: $131.81 * 1.015 = $133.79 (+1.5%)
|
||
- T2: $131.81 * 1.025 = $135.11 (+2.5%)
|
||
- T3: $131.81 * 1.04 = $137.08 (+4%) - Strike $155 ignored (too far)
|
||
|
||
## Data Fetching
|
||
|
||
### Yahoo Finance API (PRIMARY SOURCE) ⭐
|
||
**Service:** `backend/src/services/yahooFinanceService.js`
|
||
**Function:** `batchFetchYahooFinanceData(symbols)`
|
||
|
||
**API Endpoint:**
|
||
```
|
||
https://query1.finance.yahoo.com/v8/finance/chart/{symbol}?interval=1d&range=5d
|
||
```
|
||
|
||
**Returns:**
|
||
- `currentPrice` - Real-time market price
|
||
- `previousClose` - Previous day's close
|
||
- `open` - Today's open
|
||
- `high` - Today's high
|
||
- `low` - Today's low
|
||
- `volume` - Today's volume
|
||
- `volumeHistory` - Last 5 days with high/low/close/volume
|
||
|
||
**When Fetched:**
|
||
- Fetched in `optionsFlow.js` route before trade plan generation
|
||
- Passed to trade plan generator as `yahooPriceData` or `stockPriceData`
|
||
- **This is the PRIMARY source** - database is only used as fallback
|
||
|
||
### Database Queries (FALLBACK ONLY)
|
||
**Note:** Database queries are only used if Yahoo Finance data is unavailable
|
||
|
||
### Price at Signal Time (Fallback)
|
||
```sql
|
||
SELECT close, high, low, volume, ts
|
||
FROM prices_intraday_1m
|
||
WHERE UPPER(symbol) = UPPER($1)
|
||
AND ts <= $2 -- signal time
|
||
ORDER BY ts DESC
|
||
LIMIT 1
|
||
```
|
||
|
||
### RTH Open (Fallback)
|
||
```sql
|
||
SELECT open, ts
|
||
FROM prices_intraday_1m
|
||
WHERE UPPER(symbol) = UPPER($1)
|
||
AND (timezone('America/Chicago', ts))::date = $2 -- flow date
|
||
AND (timezone('America/Chicago', ts))::time >= time '09:30:00'
|
||
ORDER BY ts ASC
|
||
LIMIT 1
|
||
```
|
||
|
||
### Prior Close (Fallback)
|
||
```sql
|
||
SELECT close
|
||
FROM prices_daily
|
||
WHERE UPPER(symbol) = UPPER($1)
|
||
AND "Date" = $2 - INTERVAL '1 day' -- prior day
|
||
ORDER BY "Date" DESC
|
||
LIMIT 1
|
||
```
|
||
|
||
## Summary
|
||
|
||
**Entry Prices:** Derived from VWAP, OR levels, or current price (from Yahoo Finance)
|
||
**Stop Loss:** Percentage-based (-1.5% tight, -2.5% wide) with OR level fallback (from Yahoo Finance)
|
||
**Targets:** Percentage-based (+1.5%, +2.5%, +4%) with strike price option
|
||
**All calculations:**
|
||
- **PRIMARY:** Use Yahoo Finance real-time data (currentPrice, open, high, low, previousClose, volumeHistory)
|
||
- **FALLBACK:** Use database data only if Yahoo Finance unavailable
|
||
- Validate all levels against current price to avoid stale data
|
||
|
||
**Key Change:** Trade plans now use **Yahoo Finance API** as the primary data source for all price calculations, ensuring real-time accuracy instead of stale database data.
|
||
|