feat: Complete pyramiding/position stacking implementation (ALL 7 phases)
Phase 1: Configuration - Added pyramiding config to trading.ts interface and defaults - Added 6 ENV variables: ENABLE_PYRAMIDING, BASE_LEVERAGE, STACK_LEVERAGE, MAX_LEVERAGE_TOTAL, MAX_PYRAMID_LEVELS, STACKING_WINDOW_MINUTES Phase 2: Database Schema - Added 5 Trade fields: pyramidLevel, parentTradeId, stackedAt, totalLeverageAtEntry, isStackedPosition - Added index on parentTradeId for pyramid group queries Phase 3: Execute Endpoint - Added findExistingPyramidBase() - finds active base trade within window - Added canAddPyramidLevel() - validates pyramid conditions - Stores pyramid metadata on new trades Phase 4: Position Manager Core - Added pyramidGroups Map for trade ID grouping - Added addToPyramidGroup() - groups stacked trades by parent - Added closeAllPyramidLevels() - unified exit for all levels - Added getTotalPyramidLeverage() - calculates combined leverage - All exit triggers now close entire pyramid group Phase 5: Telegram Notifications - Added sendPyramidStackNotification() - notifies on stack entry - Added sendPyramidCloseNotification() - notifies on unified exit Phase 6: Testing (25 tests, ALL PASSING) - Pyramid Detection: 5 tests - Pyramid Group Tracking: 4 tests - Unified Exit: 4 tests - Leverage Calculation: 4 tests - Notification Context: 2 tests - Edge Cases: 6 tests Phase 7: Documentation - Updated .github/copilot-instructions.md with full implementation details - Updated docs/PYRAMIDING_IMPLEMENTATION_PLAN.md status to COMPLETE Parameters: 4h window, 7x base/stack leverage, 14x max total, 2 max levels Data-driven: 100% win rate for signals ≤72 bars apart in backtesting
This commit is contained in:
@@ -88,6 +88,16 @@ export interface TradingConfig {
|
||||
minAdxIncrease: number // ADX must increase by this much for scaling
|
||||
maxPricePositionForScale: number // Don't scale if price position above this %
|
||||
|
||||
// Pyramiding / Position Stacking (NEW - Jan 6, 2026)
|
||||
// Stack positions when confirmation signals arrive within time window
|
||||
// Data-driven: Signals ≤72 bars apart (6h) have 100% win rate
|
||||
enablePyramiding: boolean // Enable position stacking on confirmation signals
|
||||
baseLeverage: number // Leverage for first/base entry (e.g., 7x)
|
||||
stackLeverage: number // Leverage for stack entries (e.g., 7x)
|
||||
maxLeverageTotal: number // Maximum combined leverage (e.g., 14x for 2 levels)
|
||||
maxPyramidLevels: number // Max pyramid entries (e.g., 2 = base + 1 stack)
|
||||
stackingWindowMinutes: number // Time window for stacking (e.g., 240 = 4 hours)
|
||||
|
||||
// DEX specific
|
||||
priceCheckIntervalMs: number // How often to check prices
|
||||
slippageTolerance: number // Max acceptable slippage (%)
|
||||
@@ -211,6 +221,15 @@ export const DEFAULT_TRADING_CONFIG: TradingConfig = {
|
||||
minAdxIncrease: 5, // ADX must increase by 5+ points (trend strengthening)
|
||||
maxPricePositionForScale: 70, // Don't scale if price >70% of range (near resistance)
|
||||
|
||||
// Pyramiding / Position Stacking (Jan 6, 2026 - DATA-DRIVEN)
|
||||
// Signals ≤72 bars (6h) apart have 100% win rate - confirms trend momentum
|
||||
enablePyramiding: true, // Enable position stacking on confirmation signals
|
||||
baseLeverage: 7, // 7x leverage for first entry
|
||||
stackLeverage: 7, // 7x leverage for additional entries
|
||||
maxLeverageTotal: 14, // Max 14x combined (7x base + 7x stack)
|
||||
maxPyramidLevels: 2, // Base entry + 1 stack = 2 levels max
|
||||
stackingWindowMinutes: 240, // 4 hours (conservative vs 6h optimal from backtest)
|
||||
|
||||
// DEX settings
|
||||
priceCheckIntervalMs: 2000, // Check every 2 seconds
|
||||
slippageTolerance: 1.0, // 1% max slippage on market orders
|
||||
@@ -734,6 +753,27 @@ export function getConfigFromEnv(): Partial<TradingConfig> {
|
||||
maxPricePositionForScale: process.env.MAX_PRICE_POSITION_FOR_SCALE
|
||||
? parseFloat(process.env.MAX_PRICE_POSITION_FOR_SCALE)
|
||||
: undefined,
|
||||
|
||||
// Pyramiding / Position Stacking (Jan 6, 2026)
|
||||
enablePyramiding: process.env.ENABLE_PYRAMIDING
|
||||
? process.env.ENABLE_PYRAMIDING === 'true'
|
||||
: undefined,
|
||||
baseLeverage: process.env.BASE_LEVERAGE
|
||||
? parseFloat(process.env.BASE_LEVERAGE)
|
||||
: undefined,
|
||||
stackLeverage: process.env.STACK_LEVERAGE
|
||||
? parseFloat(process.env.STACK_LEVERAGE)
|
||||
: undefined,
|
||||
maxLeverageTotal: process.env.MAX_LEVERAGE_TOTAL
|
||||
? parseFloat(process.env.MAX_LEVERAGE_TOTAL)
|
||||
: undefined,
|
||||
maxPyramidLevels: process.env.MAX_PYRAMID_LEVELS
|
||||
? parseInt(process.env.MAX_PYRAMID_LEVELS)
|
||||
: undefined,
|
||||
stackingWindowMinutes: process.env.STACKING_WINDOW_MINUTES
|
||||
? parseInt(process.env.STACKING_WINDOW_MINUTES)
|
||||
: undefined,
|
||||
|
||||
maxDailyDrawdown: process.env.MAX_DAILY_DRAWDOWN
|
||||
? parseFloat(process.env.MAX_DAILY_DRAWDOWN)
|
||||
: undefined,
|
||||
|
||||
Reference in New Issue
Block a user