better vyt/sell signal proecessing/display

This commit is contained in:
Dobromir Popov
2025-12-10 01:50:18 +02:00
parent 199235962b
commit 2fea288f62
3 changed files with 135 additions and 53 deletions

View File

@@ -316,7 +316,14 @@ class RealTrainingAdapter:
return None return None
def _create_pivot_training_batch(self, model_inputs: Dict, pivot_event, inference_ref) -> Optional[Dict]: def _create_pivot_training_batch(self, model_inputs: Dict, pivot_event, inference_ref) -> Optional[Dict]:
"""Create training batch from inference inputs and pivot event""" """
Create training batch from inference inputs and pivot event
Strategy: Train to execute trades on L2 pivots that align with upper trend
- L2L (support) in UPTREND → BUY
- L2H (resistance) in DOWNTREND → SELL
- Misaligned pivots → HOLD (don't trade against trend)
"""
try: try:
import torch import torch
@@ -327,15 +334,29 @@ class RealTrainingAdapter:
# Get device # Get device
device = next(iter(batch.values())).device if batch else torch.device('cpu') device = next(iter(batch.values())).device if batch else torch.device('cpu')
# Determine action from pivot type # Get trend direction from pivot event (if available)
# L2L, L3L, etc. -> BUY (support levels) trend_direction = getattr(pivot_event, 'trend_direction', 'sideways')
# L2H, L3H, etc. -> SELL (resistance levels) pivot_type = pivot_event.pivot_type
if pivot_event.pivot_type.endswith('L'):
action = 1 # BUY # Determine action based on pivot type AND trend alignment
elif pivot_event.pivot_type.endswith('H'): # Only trade when pivot aligns with trend
action = 2 # SELL action = 0 # Default: HOLD
else:
action = 0 # HOLD if pivot_type in ['L2L', 'L3L']: # Support levels (lows)
# BUY only if in UPTREND (buying at support in uptrend)
if trend_direction in ['up', 'uptrend', 'UPTREND']:
action = 1 # BUY
logger.info(f"Pivot training: BUY signal at {pivot_type} (aligned with {trend_direction})")
else:
logger.debug(f"Pivot training: HOLD at {pivot_type} (not aligned with {trend_direction})")
elif pivot_type in ['L2H', 'L3H']: # Resistance levels (highs)
# SELL only if in DOWNTREND (selling at resistance in downtrend)
if trend_direction in ['down', 'downtrend', 'DOWNTREND']:
action = 2 # SELL
logger.info(f"Pivot training: SELL signal at {pivot_type} (aligned with {trend_direction})")
else:
logger.debug(f"Pivot training: HOLD at {pivot_type} (not aligned with {trend_direction})")
batch['actions'] = torch.tensor([[action]], dtype=torch.long, device=device) batch['actions'] = torch.tensor([[action]], dtype=torch.long, device=device)
@@ -4824,7 +4845,7 @@ class RealTrainingAdapter:
Execute trade based on signal, respecting position management rules Execute trade based on signal, respecting position management rules
Rules: Rules:
1. Only execute if confidence >= 0.6 1. Only execute if confidence >= 0.5 (lowered for more learning opportunities)
2. Only open new position if no position is currently open 2. Only open new position if no position is currently open
3. Close position on opposite signal 3. Close position on opposite signal
4. Track all executed trades for visualization 4. Track all executed trades for visualization
@@ -4836,8 +4857,8 @@ class RealTrainingAdapter:
confidence = signal['confidence'] confidence = signal['confidence']
timestamp = signal['timestamp'] timestamp = signal['timestamp']
# Rule 1: Confidence threshold # Rule 1: Confidence threshold (lowered to 0.5 for more learning opportunities)
if confidence < 0.6: if confidence < 0.5:
return None # Rejected: low confidence return None # Rejected: low confidence
# Rule 2 & 3: Position management # Rule 2 & 3: Position management
@@ -4962,8 +4983,8 @@ class RealTrainingAdapter:
confidence = signal['confidence'] confidence = signal['confidence']
position = session.get('position') position = session.get('position')
if confidence < 0.6: if confidence < 0.5:
return f"Low confidence ({confidence:.2f} < 0.6)" return f"Low confidence ({confidence:.2f} < 0.5)"
if action == 'HOLD': if action == 'HOLD':
return "HOLD signal (no trade)" return "HOLD signal (no trade)"

View File

@@ -3863,7 +3863,7 @@ class ChartManager {
// Update confidence // Update confidence
const confPct = (confidence * 100).toFixed(0); const confPct = (confidence * 100).toFixed(0);
signalConf.textContent = `${confPct}%`; signalConf.textContent = `${confPct}%`;
signalConf.style.color = confidence >= 0.6 ? '#10b981' : '#9ca3af'; signalConf.style.color = confidence >= 0.5 ? '#10b981' : '#9ca3af';
} catch (error) { } catch (error) {
console.error(`Error updating signal banner for ${timeframe}:`, error); console.error(`Error updating signal banner for ${timeframe}:`, error);

View File

@@ -1135,53 +1135,82 @@
} }
function updatePnLTracking(action, currentPrice, timestamp) { function updatePnLTracking(action, currentPrice, timestamp) {
// Simple trading simulation: BUY opens long, SELL opens short, HOLD closes positions // Paper trading simulation with proper position management
if (action === 'BUY' && pnlTracker.positions.length === 0) { // Rules:
// Open long position // 1. BUY: Close SHORT if exists, then open LONG
pnlTracker.positions.push({ // 2. SELL: Close LONG if exists, then open SHORT
action: 'BUY', // 3. HOLD: Do nothing (keep existing positions)
entryPrice: currentPrice,
entryTime: timestamp, const currentPosition = pnlTracker.positions.length > 0 ? pnlTracker.positions[0] : null;
size: pnlTracker.positionSize
}); if (action === 'BUY') {
} else if (action === 'SELL' && pnlTracker.positions.length === 0) { // Close SHORT position if exists
// Open short position if (currentPosition && currentPosition.action === 'SELL') {
pnlTracker.positions.push({ const pnl = (currentPosition.entryPrice - currentPrice) / currentPosition.entryPrice * currentPosition.size;
action: 'SELL',
entryPrice: currentPrice,
entryTime: timestamp,
size: pnlTracker.positionSize
});
} else if (action === 'HOLD' && pnlTracker.positions.length > 0) {
// Close all positions
pnlTracker.positions.forEach(pos => {
let pnl = 0;
if (pos.action === 'BUY') {
// Long: profit if price went up
pnl = (currentPrice - pos.entryPrice) / pos.entryPrice * pos.size;
} else if (pos.action === 'SELL') {
// Short: profit if price went down
pnl = (pos.entryPrice - currentPrice) / pos.entryPrice * pos.size;
}
pnlTracker.closedTrades.push({ pnlTracker.closedTrades.push({
entryPrice: pos.entryPrice, entryPrice: currentPosition.entryPrice,
exitPrice: currentPrice, exitPrice: currentPrice,
pnl: pnl, pnl: pnl,
entryTime: pos.entryTime, entryTime: currentPosition.entryTime,
exitTime: timestamp exitTime: timestamp,
type: 'SHORT'
}); });
pnlTracker.totalPnL += pnl; pnlTracker.totalPnL += pnl;
}); pnlTracker.positions = [];
console.log(`[Paper Trading] Closed SHORT @ ${currentPrice.toFixed(2)}, PnL: ${pnl >= 0 ? '+' : ''}${pnl.toFixed(2)}`);
}
pnlTracker.positions = []; // Open LONG position (if no position or just closed SHORT)
if (pnlTracker.positions.length === 0) {
pnlTracker.positions.push({
action: 'BUY',
entryPrice: currentPrice,
entryTime: timestamp,
size: pnlTracker.positionSize
});
console.log(`[Paper Trading] Opened LONG @ ${currentPrice.toFixed(2)}`);
}
// Calculate win rate } else if (action === 'SELL') {
// Close LONG position if exists
if (currentPosition && currentPosition.action === 'BUY') {
const pnl = (currentPrice - currentPosition.entryPrice) / currentPosition.entryPrice * currentPosition.size;
pnlTracker.closedTrades.push({
entryPrice: currentPosition.entryPrice,
exitPrice: currentPrice,
pnl: pnl,
entryTime: currentPosition.entryTime,
exitTime: timestamp,
type: 'LONG'
});
pnlTracker.totalPnL += pnl;
pnlTracker.positions = [];
console.log(`[Paper Trading] Closed LONG @ ${currentPrice.toFixed(2)}, PnL: ${pnl >= 0 ? '+' : ''}${pnl.toFixed(2)}`);
}
// Open SHORT position (if no position or just closed LONG)
if (pnlTracker.positions.length === 0) {
pnlTracker.positions.push({
action: 'SELL',
entryPrice: currentPrice,
entryTime: timestamp,
size: pnlTracker.positionSize
});
console.log(`[Paper Trading] Opened SHORT @ ${currentPrice.toFixed(2)}`);
}
}
// HOLD: Do nothing, keep existing positions
// Calculate win rate
if (pnlTracker.closedTrades.length > 0) {
const wins = pnlTracker.closedTrades.filter(t => t.pnl > 0).length; const wins = pnlTracker.closedTrades.filter(t => t.pnl > 0).length;
pnlTracker.winRate = pnlTracker.closedTrades.length > 0 pnlTracker.winRate = (wins / pnlTracker.closedTrades.length * 100);
? (wins / pnlTracker.closedTrades.length * 100)
: 0;
} }
// Update PnL display // Update PnL display
@@ -1192,6 +1221,38 @@
const pnlColor = pnlTracker.totalPnL >= 0 ? 'text-success' : 'text-danger'; const pnlColor = pnlTracker.totalPnL >= 0 ? 'text-success' : 'text-danger';
const pnlSign = pnlTracker.totalPnL >= 0 ? '+' : ''; const pnlSign = pnlTracker.totalPnL >= 0 ? '+' : '';
// Update position status in trading panel
const positionStatusEl = document.getElementById('position-status');
if (positionStatusEl) {
if (pnlTracker.positions.length > 0) {
const pos = pnlTracker.positions[0];
const posType = pos.action === 'BUY' ? 'LONG' : 'SHORT';
const posColor = pos.action === 'BUY' ? 'text-success' : 'text-danger';
positionStatusEl.textContent = posType;
positionStatusEl.className = `fw-bold ${posColor}`;
} else {
positionStatusEl.textContent = 'NO POSITION';
positionStatusEl.className = 'fw-bold text-info';
}
}
// Update session PnL
const sessionPnlEl = document.getElementById('session-pnl');
if (sessionPnlEl) {
sessionPnlEl.textContent = `${pnlSign}$${pnlTracker.totalPnL.toFixed(2)}`;
sessionPnlEl.className = `fw-bold ${pnlColor}`;
}
// Update win rate
const winRateEl = document.getElementById('win-rate');
if (winRateEl) {
const wins = pnlTracker.closedTrades.filter(t => t.pnl > 0).length;
const total = pnlTracker.closedTrades.length;
winRateEl.textContent = total > 0
? `${pnlTracker.winRate.toFixed(0)}% (${wins}/${total})`
: '0% (0/0)';
}
// Update PnL metric // Update PnL metric
const pnlElement = document.getElementById('metric-pnl'); const pnlElement = document.getElementById('metric-pnl');
if (pnlElement) { if (pnlElement) {