Files
trading_bot_v4/fix_zero_pnl_trades.sql
mindesbunister 881a99242d feat: Add per-symbol trading controls for SOL and ETH
- Add SymbolSettings interface with enabled/positionSize/leverage fields
- Implement per-symbol ENV variables (SOLANA_*, ETHEREUM_*)
- Add SOL and ETH sections to settings UI with enable/disable toggles
- Add symbol-specific test buttons (SOL LONG/SHORT, ETH LONG/SHORT)
- Update execute and test endpoints to check symbol enabled status
- Add real-time risk/reward calculator per symbol
- Rename 'Position Sizing' to 'Global Fallback' for clarity
- Fix position manager P&L calculation for externally closed positions
- Fix zero P&L bug affecting 12 historical trades
- Add SQL scripts for recalculating historical P&L data
- Move archive TypeScript files to .archive to fix build

Defaults:
- SOL: 10 base × 10x leverage = 100 notional (profit trading)
- ETH:  base × 1x leverage =  notional (data collection)
- Global: 10 × 10x for BTC and other symbols

Configuration priority: Per-symbol ENV > Market config > Global ENV > Defaults
2025-11-03 10:28:48 +01:00

80 lines
2.6 KiB
SQL

-- Fix Zero P&L Trades
-- This script recalculates P&L for trades that were incorrectly recorded as $0.00
-- Created: 2025-11-03
-- Backup: backup_before_pnl_fix_20251103_091248.sql
-- First, let's see what we're fixing
SELECT
id,
symbol,
direction,
ROUND("entryPrice"::numeric, 2) as entry,
ROUND("exitPrice"::numeric, 2) as exit,
"positionSizeUSD",
leverage,
"realizedPnL" as current_pnl,
"exitReason"
FROM "Trade"
WHERE "realizedPnL" = 0
AND "exitReason" IS NOT NULL
AND "exitPrice" IS NOT NULL
AND "exitOrderTx" IN ('ON_CHAIN_ORDER', 'UNKNOWN_CLOSURE')
ORDER BY "entryTime" DESC;
-- Calculate and update P&L for zero-P&L trades
-- Formula: realizedPnL = (positionSizeUSD * profitPercent * leverage) / 100
-- profitPercent = ((exitPrice - entryPrice) / entryPrice) * 100 * (direction multiplier)
UPDATE "Trade"
SET
"realizedPnL" = CASE
WHEN direction = 'long' THEN
-- Long: profit when exit > entry
("positionSizeUSD" * ((("exitPrice" - "entryPrice") / "entryPrice") * 100) * leverage) / 100
WHEN direction = 'short' THEN
-- Short: profit when exit < entry
("positionSizeUSD" * ((("entryPrice" - "exitPrice") / "entryPrice") * 100) * leverage) / 100
ELSE 0
END,
"realizedPnLPercent" = CASE
WHEN direction = 'long' THEN
((("exitPrice" - "entryPrice") / "entryPrice") * 100) * leverage
WHEN direction = 'short' THEN
((("entryPrice" - "exitPrice") / "entryPrice") * 100) * leverage
ELSE 0
END,
"updatedAt" = NOW()
WHERE "realizedPnL" = 0
AND "exitReason" IS NOT NULL
AND "exitPrice" IS NOT NULL
AND "exitOrderTx" IN ('ON_CHAIN_ORDER', 'UNKNOWN_CLOSURE');
-- Show the results after fix
SELECT
id,
symbol,
direction,
ROUND("entryPrice"::numeric, 2) as entry,
ROUND("exitPrice"::numeric, 2) as exit,
ROUND("positionSizeUSD"::numeric, 2) as size,
leverage,
ROUND("realizedPnL"::numeric, 2) as fixed_pnl,
ROUND("realizedPnLPercent"::numeric, 2) as pnl_percent,
"exitReason"
FROM "Trade"
WHERE "exitOrderTx" IN ('ON_CHAIN_ORDER', 'UNKNOWN_CLOSURE')
AND "exitReason" IS NOT NULL
ORDER BY "entryTime" DESC;
-- Show new total P&L
SELECT
COUNT(*) as total_trades,
SUM(CASE WHEN "realizedPnL" > 0 THEN 1 ELSE 0 END) as wins,
SUM(CASE WHEN "realizedPnL" <= 0 THEN 1 ELSE 0 END) as losses,
ROUND(SUM("realizedPnL")::numeric, 2) as total_pnl,
ROUND(AVG(CASE WHEN "realizedPnL" > 0 THEN "realizedPnL" END)::numeric, 2) as avg_win,
ROUND(AVG(CASE WHEN "realizedPnL" <= 0 THEN "realizedPnL" END)::numeric, 2) as avg_loss
FROM "Trade"
WHERE "entryTime" >= NOW() - INTERVAL '7 days'
AND "exitReason" IS NOT NULL;