Make TP2 the runner - no more partial closes
CHANGE: TP2 now activates trailing stop on full 25% remaining instead of closing 80% and leaving 5% runner. Benefits: - 5x larger runner (25% vs 5%) = 25 vs 05 on 100 position - Eliminates Drift minimum size issues completely - Simplifies logic - no more canUseRunner() viability checks - Better R:R on extended moves New flow: - TP1 (+0.4%): Close 75%, keep 25% - TP2 (+0.7%): Skip close, activate trailing stop on full 25% - Runner: 25% with ATR-based trailing (0.25-0.9%) Config change: takeProfit2SizePercent: 80 → 0 Position Manager: Remove canUseRunner logic, activate trailing at TP2 hit
This commit is contained in:
@@ -145,8 +145,9 @@ export const DEFAULT_TRADING_CONFIG: TradingConfig = {
|
||||
// Execution
|
||||
useMarketOrders: true, // Use market orders for reliable fills
|
||||
confirmationTimeout: 30000, // 30 seconds max wait
|
||||
takeProfit1SizePercent: 75, // Close 75% at TP1 to lock in profit
|
||||
takeProfit2SizePercent: 80, // Close 80% of remaining 25% at TP2 (leaves 5% as runner)
|
||||
// Position sizing (percentages of position to close at each TP)
|
||||
takeProfit1SizePercent: 75, // Close 75% at TP1 (leaves 25% for TP2 + runner)
|
||||
takeProfit2SizePercent: 0, // Don't close at TP2 - let full 25% remaining become the runner
|
||||
}
|
||||
|
||||
// Supported markets on Drift Protocol
|
||||
|
||||
@@ -9,7 +9,6 @@ import { closePosition } from '../drift/orders'
|
||||
import { getPythPriceMonitor, PriceUpdate } from '../pyth/price-monitor'
|
||||
import { getMergedConfig, TradingConfig, getMarketConfig } from '../../config/trading'
|
||||
import { updateTradeExit, updateTradeState, getOpenTrades } from '../database/trades'
|
||||
import { canUseRunner, getViableTP2Percent } from './runner-calculator'
|
||||
|
||||
export interface ActiveTrade {
|
||||
id: string
|
||||
@@ -704,61 +703,24 @@ export class PositionManager {
|
||||
await this.saveTradeState(trade)
|
||||
}
|
||||
|
||||
// 5. Take profit 2 (remaining position)
|
||||
// 5. TP2 Hit - Activate runner (no close, just start trailing)
|
||||
if (trade.tp1Hit && !trade.tp2Hit && this.shouldTakeProfit2(currentPrice, trade)) {
|
||||
console.log(`🎊 TP2 HIT: ${trade.symbol} at ${profitPercent.toFixed(2)}%`)
|
||||
console.log(`🎊 TP2 HIT: ${trade.symbol} at ${profitPercent.toFixed(2)}% - Activating 25% runner!`)
|
||||
|
||||
// Check if runner would be viable with current position size
|
||||
const runnerCheck = canUseRunner(
|
||||
trade.symbol,
|
||||
trade.currentSize,
|
||||
currentPrice,
|
||||
this.config.takeProfit1SizePercent,
|
||||
this.config.takeProfit2SizePercent
|
||||
// Mark TP2 as hit and activate trailing stop on full remaining 25%
|
||||
trade.tp2Hit = true
|
||||
trade.peakPrice = currentPrice
|
||||
trade.runnerTrailingPercent = this.getRunnerTrailingPercent(trade)
|
||||
|
||||
console.log(
|
||||
`🏃 Runner activated on full remaining position: ${((trade.currentSize / trade.positionSize) * 100).toFixed(1)}% | trailing buffer ${trade.runnerTrailingPercent?.toFixed(3)}%`
|
||||
)
|
||||
|
||||
if (!runnerCheck.viable) {
|
||||
console.log(`⚠️ Runner not viable: ${runnerCheck.reason}`)
|
||||
console.log(` Skipping TP2 close, will use trailing stop on full 25% remaining`)
|
||||
|
||||
// Mark TP2 as "hit" but don't close anything - activate trailing on full 25%
|
||||
trade.tp2Hit = true
|
||||
trade.trailingStopActive = true
|
||||
trade.runnerTrailingPercent = this.getRunnerTrailingPercent(trade)
|
||||
|
||||
console.log(
|
||||
`🏃 Runner activated on full remaining position: ${((trade.currentSize / trade.positionSize) * 100).toFixed(1)}% | trailing buffer ${trade.runnerTrailingPercent?.toFixed(3)}%`
|
||||
)
|
||||
|
||||
await this.saveTradeState(trade)
|
||||
return
|
||||
}
|
||||
|
||||
// Runner is viable - proceed with TP2 close
|
||||
const percentToClose = this.config.takeProfit2SizePercent
|
||||
|
||||
console.log(`✅ Runner viable: ${runnerCheck.runnerSizeBase.toFixed(4)} base (${runnerCheck.runnerSizeUSD.toFixed(2)} USD)`)
|
||||
|
||||
await this.executeExit(trade, percentToClose, 'TP2', currentPrice)
|
||||
|
||||
// If some position remains, mark TP2 as hit and activate trailing stop
|
||||
if (percentToClose < 100) {
|
||||
trade.tp2Hit = true
|
||||
trade.currentSize = trade.currentSize * ((100 - percentToClose) / 100)
|
||||
trade.runnerTrailingPercent = this.getRunnerTrailingPercent(trade)
|
||||
|
||||
console.log(
|
||||
`🏃 Runner activated: ${((trade.currentSize / trade.positionSize) * 100).toFixed(1)}% remaining | trailing buffer ${trade.runnerTrailingPercent?.toFixed(3)}%`
|
||||
)
|
||||
|
||||
// Save state after TP2
|
||||
await this.saveTradeState(trade)
|
||||
}
|
||||
// Save state after TP2 activation
|
||||
await this.saveTradeState(trade)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 6. Trailing stop for runner (after TP2)
|
||||
} // 6. Trailing stop for runner (after TP2 activation)
|
||||
if (trade.tp2Hit && this.config.useTrailingStop) {
|
||||
// Check if trailing stop should be activated
|
||||
if (!trade.trailingStopActive && profitPercent >= this.config.trailingStopActivation) {
|
||||
|
||||
Reference in New Issue
Block a user