feat: Implement ATR-based dynamic TP2 system and fix P&L calculation
- Add ATR-based dynamic TP2 scaling from 0.7% to 3.0% based on volatility - New config options: useAtrBasedTargets, atrMultiplierForTp2, minTp2Percent, maxTp2Percent - Enhanced settings UI with ATR controls and updated risk calculator - Fix external closure P&L calculation using unrealized P&L instead of volatile current price - Update execute and test endpoints to use calculateDynamicTp2() function - Maintain 25% runner system for capturing extended moves (4-5% targets) - Add environment variables for ATR-based configuration - Better P&L accuracy for manual position closures
This commit is contained in:
@@ -97,6 +97,12 @@ export async function GET() {
|
||||
TRAILING_STOP_MAX_PERCENT: parseFloat(env.TRAILING_STOP_MAX_PERCENT || '0.9'),
|
||||
TRAILING_STOP_ACTIVATION: parseFloat(env.TRAILING_STOP_ACTIVATION || '0.5'),
|
||||
|
||||
// ATR-based Dynamic Targets
|
||||
USE_ATR_BASED_TARGETS: env.USE_ATR_BASED_TARGETS === 'true' || env.USE_ATR_BASED_TARGETS === undefined,
|
||||
ATR_MULTIPLIER_FOR_TP2: parseFloat(env.ATR_MULTIPLIER_FOR_TP2 || '2.0'),
|
||||
MIN_TP2_PERCENT: parseFloat(env.MIN_TP2_PERCENT || '0.7'),
|
||||
MAX_TP2_PERCENT: parseFloat(env.MAX_TP2_PERCENT || '3.0'),
|
||||
|
||||
// Position Scaling
|
||||
ENABLE_POSITION_SCALING: env.ENABLE_POSITION_SCALING === 'true',
|
||||
MIN_SCALE_QUALITY_SCORE: parseInt(env.MIN_SCALE_QUALITY_SCORE || '75'),
|
||||
@@ -158,6 +164,12 @@ export async function POST(request: NextRequest) {
|
||||
TRAILING_STOP_MAX_PERCENT: (settings.TRAILING_STOP_MAX_PERCENT ?? DEFAULT_TRADING_CONFIG.trailingStopMaxPercent).toString(),
|
||||
TRAILING_STOP_ACTIVATION: settings.TRAILING_STOP_ACTIVATION.toString(),
|
||||
|
||||
// ATR-based Dynamic Targets
|
||||
USE_ATR_BASED_TARGETS: (settings as any).USE_ATR_BASED_TARGETS?.toString() || 'true',
|
||||
ATR_MULTIPLIER_FOR_TP2: (settings as any).ATR_MULTIPLIER_FOR_TP2?.toString() || '2.0',
|
||||
MIN_TP2_PERCENT: (settings as any).MIN_TP2_PERCENT?.toString() || '0.7',
|
||||
MAX_TP2_PERCENT: (settings as any).MAX_TP2_PERCENT?.toString() || '3.0',
|
||||
|
||||
// Position Scaling
|
||||
ENABLE_POSITION_SCALING: settings.ENABLE_POSITION_SCALING.toString(),
|
||||
MIN_SCALE_QUALITY_SCORE: settings.MIN_SCALE_QUALITY_SCORE.toString(),
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { initializeDriftService } from '@/lib/drift/client'
|
||||
import { openPosition, placeExitOrders } from '@/lib/drift/orders'
|
||||
import { normalizeTradingViewSymbol } from '@/config/trading'
|
||||
import { normalizeTradingViewSymbol, calculateDynamicTp2 } from '@/config/trading'
|
||||
import { getMergedConfig } from '@/config/trading'
|
||||
import { getInitializedPositionManager, ActiveTrade } from '@/lib/trading/position-manager'
|
||||
import { createTrade, updateTradeExit } from '@/lib/database/trades'
|
||||
@@ -420,9 +420,15 @@ export async function POST(request: NextRequest): Promise<NextResponse<ExecuteTr
|
||||
body.direction
|
||||
)
|
||||
|
||||
const dynamicTp2Percent = calculateDynamicTp2(
|
||||
entryPrice,
|
||||
body.atr || 0, // ATR from TradingView signal
|
||||
config
|
||||
)
|
||||
|
||||
const tp2Price = calculatePrice(
|
||||
entryPrice,
|
||||
config.takeProfit2Percent,
|
||||
dynamicTp2Percent,
|
||||
body.direction
|
||||
)
|
||||
|
||||
@@ -430,7 +436,7 @@ export async function POST(request: NextRequest): Promise<NextResponse<ExecuteTr
|
||||
console.log(` Entry: $${entryPrice.toFixed(4)}`)
|
||||
console.log(` SL: $${stopLossPrice.toFixed(4)} (${config.stopLossPercent}%)`)
|
||||
console.log(` TP1: $${tp1Price.toFixed(4)} (${config.takeProfit1Percent}%)`)
|
||||
console.log(` TP2: $${tp2Price.toFixed(4)} (${config.takeProfit2Percent}%)`)
|
||||
console.log(` TP2: $${tp2Price.toFixed(4)} (${dynamicTp2Percent.toFixed(2)}% - ATR-based)`)
|
||||
|
||||
// Calculate emergency stop
|
||||
const emergencyStopPrice = calculatePrice(
|
||||
@@ -532,7 +538,7 @@ export async function POST(request: NextRequest): Promise<NextResponse<ExecuteTr
|
||||
takeProfit2: tp2Price,
|
||||
stopLossPercent: config.stopLossPercent,
|
||||
tp1Percent: config.takeProfit1Percent,
|
||||
tp2Percent: config.takeProfit2Percent,
|
||||
tp2Percent: dynamicTp2Percent,
|
||||
entrySlippage: openResult.slippage,
|
||||
timestamp: new Date().toISOString(),
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { initializeDriftService } from '@/lib/drift/client'
|
||||
import { openPosition, placeExitOrders } from '@/lib/drift/orders'
|
||||
import { normalizeTradingViewSymbol } from '@/config/trading'
|
||||
import { normalizeTradingViewSymbol, calculateDynamicTp2 } from '@/config/trading'
|
||||
import { getMergedConfig } from '@/config/trading'
|
||||
import { getInitializedPositionManager, ActiveTrade } from '@/lib/trading/position-manager'
|
||||
import { createTrade } from '@/lib/database/trades'
|
||||
@@ -172,9 +172,18 @@ export async function POST(request: NextRequest): Promise<NextResponse<TestTrade
|
||||
direction
|
||||
)
|
||||
|
||||
// Use ATR-based dynamic TP2 with simulated ATR for testing
|
||||
const simulatedATR = entryPrice * 0.008 // Simulate 0.8% ATR for testing
|
||||
|
||||
const dynamicTp2Percent = calculateDynamicTp2(
|
||||
entryPrice,
|
||||
simulatedATR,
|
||||
config
|
||||
)
|
||||
|
||||
const tp2Price = calculatePrice(
|
||||
entryPrice,
|
||||
config.takeProfit2Percent,
|
||||
dynamicTp2Percent,
|
||||
direction
|
||||
)
|
||||
|
||||
@@ -182,7 +191,7 @@ export async function POST(request: NextRequest): Promise<NextResponse<TestTrade
|
||||
console.log(` Entry: $${entryPrice.toFixed(4)}`)
|
||||
console.log(` SL: $${stopLossPrice.toFixed(4)} (${config.stopLossPercent}%)`)
|
||||
console.log(` TP1: $${tp1Price.toFixed(4)} (${config.takeProfit1Percent}%)`)
|
||||
console.log(` TP2: $${tp2Price.toFixed(4)} (${config.takeProfit2Percent}%)`)
|
||||
console.log(` TP2: $${tp2Price.toFixed(4)} (${dynamicTp2Percent.toFixed(2)}% - ATR-based test)`)
|
||||
|
||||
// Calculate emergency stop
|
||||
const emergencyStopPrice = calculatePrice(
|
||||
|
||||
Reference in New Issue
Block a user