feat: implement AI-driven dynamic leverage calculator
- Under k: Use 100% of available balance for maximum growth - Over k: Use 50% balance for controlled risk management - AI calculates optimal leverage maintaining safe liquidation distance - Liquidation price stays safely below stop loss (10% buffer) New Features: - AILeverageCalculator class with sophisticated risk assessment - Dynamic position sizing based on account value and market conditions - Liquidation price calculation and safety validation - Risk assessment levels (LOW/MEDIUM/HIGH) with reasoning - Support for both long and short positions with AI leverage - Enhanced automation-service-simple.ts with AI leverage - Position sizing now returns leverage + risk metrics - Trade execution uses AI-calculated leverage values - Database storage includes AI leverage metadata - Comprehensive logging for leverage decisions - Safety buffer prevents liquidation near stop loss - Maximum leverage limited by platform constraints (20x) - Account-based strategy (aggressive <k, conservative >k) - Real-time balance and position validation This enables maximum profit potential while maintaining strict risk controls.
This commit is contained in:
251
lib/ai-leverage-calculator.ts
Normal file
251
lib/ai-leverage-calculator.ts
Normal file
@@ -0,0 +1,251 @@
|
|||||||
|
/**
|
||||||
|
* AI-Driven Dynamic Leverage Calculator
|
||||||
|
*
|
||||||
|
* Calculates optimal leverage to maximize profits while maintaining safe liquidation distance
|
||||||
|
* Strategy: Use maximum leverage possible without liquidation price being too close to stop loss
|
||||||
|
*/
|
||||||
|
|
||||||
|
interface LeverageCalculationParams {
|
||||||
|
accountValue: number
|
||||||
|
availableBalance: number
|
||||||
|
entryPrice: number
|
||||||
|
stopLossPrice: number
|
||||||
|
side: 'long' | 'short'
|
||||||
|
maxLeverageAllowed: number // Platform maximum (e.g., 20x for Drift)
|
||||||
|
safetyBuffer: number // Distance between liquidation and SL (default: 10%)
|
||||||
|
}
|
||||||
|
|
||||||
|
interface LeverageResult {
|
||||||
|
recommendedLeverage: number
|
||||||
|
positionSize: number
|
||||||
|
liquidationPrice: number
|
||||||
|
marginRequired: number
|
||||||
|
maxPossibleLeverage: number
|
||||||
|
riskAssessment: 'LOW' | 'MEDIUM' | 'HIGH'
|
||||||
|
reasoning: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export class AILeverageCalculator {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate optimal leverage for maximum profit with safe liquidation distance
|
||||||
|
*/
|
||||||
|
static calculateOptimalLeverage(params: LeverageCalculationParams): LeverageResult {
|
||||||
|
const {
|
||||||
|
accountValue,
|
||||||
|
availableBalance,
|
||||||
|
entryPrice,
|
||||||
|
stopLossPrice,
|
||||||
|
side,
|
||||||
|
maxLeverageAllowed,
|
||||||
|
safetyBuffer = 0.10 // 10% safety buffer by default
|
||||||
|
} = params
|
||||||
|
|
||||||
|
console.log('🧮 AI Leverage Calculation:', {
|
||||||
|
accountValue: accountValue.toFixed(2),
|
||||||
|
availableBalance: availableBalance.toFixed(2),
|
||||||
|
entryPrice,
|
||||||
|
stopLossPrice,
|
||||||
|
side,
|
||||||
|
maxLeverageAllowed
|
||||||
|
})
|
||||||
|
|
||||||
|
// Strategy 1: Under $1k - Use 100% of available balance
|
||||||
|
const useFullBalance = accountValue < 1000
|
||||||
|
const baseAmount = useFullBalance ? availableBalance : availableBalance * 0.5 // 50% for accounts over $1k
|
||||||
|
|
||||||
|
console.log(`💰 Balance Strategy: ${useFullBalance ? 'AGGRESSIVE (100%)' : 'CONSERVATIVE (50%)'} - Using $${baseAmount.toFixed(2)}`)
|
||||||
|
|
||||||
|
// Calculate stop loss distance as percentage
|
||||||
|
const stopLossDistance = Math.abs(entryPrice - stopLossPrice) / entryPrice
|
||||||
|
console.log(`📊 Stop Loss Distance: ${(stopLossDistance * 100).toFixed(2)}%`)
|
||||||
|
|
||||||
|
// Calculate maximum safe leverage based on liquidation distance
|
||||||
|
const maxSafeLeverage = this.calculateMaxSafeLeverage(
|
||||||
|
entryPrice,
|
||||||
|
stopLossPrice,
|
||||||
|
side,
|
||||||
|
safetyBuffer
|
||||||
|
)
|
||||||
|
|
||||||
|
// Determine final leverage (limited by platform max and safety calculations)
|
||||||
|
const finalLeverage = Math.min(maxSafeLeverage, maxLeverageAllowed)
|
||||||
|
|
||||||
|
// Calculate position size and margin
|
||||||
|
const positionSize = baseAmount * finalLeverage
|
||||||
|
const marginRequired = positionSize / finalLeverage
|
||||||
|
|
||||||
|
// Calculate liquidation price for verification
|
||||||
|
const liquidationPrice = this.calculateLiquidationPrice(
|
||||||
|
entryPrice,
|
||||||
|
finalLeverage,
|
||||||
|
side,
|
||||||
|
marginRequired,
|
||||||
|
positionSize
|
||||||
|
)
|
||||||
|
|
||||||
|
// Risk assessment
|
||||||
|
const riskAssessment = this.assessRisk(finalLeverage, stopLossDistance, useFullBalance)
|
||||||
|
|
||||||
|
// Generate AI reasoning
|
||||||
|
const reasoning = this.generateLeverageReasoning(
|
||||||
|
finalLeverage,
|
||||||
|
maxSafeLeverage,
|
||||||
|
maxLeverageAllowed,
|
||||||
|
liquidationPrice,
|
||||||
|
stopLossPrice,
|
||||||
|
useFullBalance,
|
||||||
|
side
|
||||||
|
)
|
||||||
|
|
||||||
|
const result: LeverageResult = {
|
||||||
|
recommendedLeverage: finalLeverage,
|
||||||
|
positionSize,
|
||||||
|
liquidationPrice,
|
||||||
|
marginRequired,
|
||||||
|
maxPossibleLeverage: maxSafeLeverage,
|
||||||
|
riskAssessment,
|
||||||
|
reasoning
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('🎯 AI Leverage Result:', {
|
||||||
|
recommendedLeverage: `${finalLeverage.toFixed(1)}x`,
|
||||||
|
positionSize: `$${positionSize.toFixed(2)}`,
|
||||||
|
liquidationPrice: `$${liquidationPrice.toFixed(4)}`,
|
||||||
|
riskAssessment,
|
||||||
|
reasoning
|
||||||
|
})
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate maximum safe leverage where liquidation price maintains safety buffer from stop loss
|
||||||
|
*/
|
||||||
|
private static calculateMaxSafeLeverage(
|
||||||
|
entryPrice: number,
|
||||||
|
stopLossPrice: number,
|
||||||
|
side: 'long' | 'short',
|
||||||
|
safetyBuffer: number
|
||||||
|
): number {
|
||||||
|
|
||||||
|
// Calculate where liquidation should be (beyond stop loss + safety buffer)
|
||||||
|
let maxLiquidationPrice: number
|
||||||
|
|
||||||
|
if (side === 'long') {
|
||||||
|
// For longs: liquidation should be below stop loss
|
||||||
|
maxLiquidationPrice = stopLossPrice * (1 - safetyBuffer)
|
||||||
|
} else {
|
||||||
|
// For shorts: liquidation should be above stop loss
|
||||||
|
maxLiquidationPrice = stopLossPrice * (1 + safetyBuffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`🛡️ Max Safe Liquidation Price: $${maxLiquidationPrice.toFixed(4)} (${side} position)`)
|
||||||
|
|
||||||
|
// Calculate max leverage that keeps liquidation at safe distance
|
||||||
|
// Simplified liquidation formula: For longs: liq = entry * (1 - 1/leverage)
|
||||||
|
let maxLeverage: number
|
||||||
|
|
||||||
|
if (side === 'long') {
|
||||||
|
// entry * (1 - 1/leverage) = maxLiquidationPrice
|
||||||
|
// 1 - 1/leverage = maxLiquidationPrice / entry
|
||||||
|
// 1/leverage = 1 - maxLiquidationPrice / entry
|
||||||
|
// leverage = 1 / (1 - maxLiquidationPrice / entry)
|
||||||
|
maxLeverage = 1 / (1 - maxLiquidationPrice / entryPrice)
|
||||||
|
} else {
|
||||||
|
// For shorts: liq = entry * (1 + 1/leverage)
|
||||||
|
// entry * (1 + 1/leverage) = maxLiquidationPrice
|
||||||
|
// 1 + 1/leverage = maxLiquidationPrice / entry
|
||||||
|
// 1/leverage = maxLiquidationPrice / entry - 1
|
||||||
|
// leverage = 1 / (maxLiquidationPrice / entry - 1)
|
||||||
|
maxLeverage = 1 / (maxLiquidationPrice / entryPrice - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure reasonable bounds
|
||||||
|
maxLeverage = Math.max(1, Math.min(maxLeverage, 50)) // Between 1x and 50x
|
||||||
|
|
||||||
|
console.log(`⚖️ Max Safe Leverage: ${maxLeverage.toFixed(2)}x`)
|
||||||
|
|
||||||
|
return maxLeverage
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate liquidation price for given position parameters
|
||||||
|
*/
|
||||||
|
private static calculateLiquidationPrice(
|
||||||
|
entryPrice: number,
|
||||||
|
leverage: number,
|
||||||
|
side: 'long' | 'short',
|
||||||
|
marginRequired: number,
|
||||||
|
positionSize: number
|
||||||
|
): number {
|
||||||
|
|
||||||
|
// Simplified liquidation calculation
|
||||||
|
// In reality, this would need to account for fees, funding, etc.
|
||||||
|
|
||||||
|
if (side === 'long') {
|
||||||
|
// Long liquidation: entry * (1 - 1/leverage)
|
||||||
|
return entryPrice * (1 - 1/leverage)
|
||||||
|
} else {
|
||||||
|
// Short liquidation: entry * (1 + 1/leverage)
|
||||||
|
return entryPrice * (1 + 1/leverage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assess risk level based on leverage and position parameters
|
||||||
|
*/
|
||||||
|
private static assessRisk(
|
||||||
|
leverage: number,
|
||||||
|
stopLossDistance: number,
|
||||||
|
useFullBalance: boolean
|
||||||
|
): 'LOW' | 'MEDIUM' | 'HIGH' {
|
||||||
|
|
||||||
|
if (leverage <= 2 && stopLossDistance >= 0.05) return 'LOW'
|
||||||
|
if (leverage <= 5 && stopLossDistance >= 0.03) return 'MEDIUM'
|
||||||
|
if (leverage <= 10 && stopLossDistance >= 0.02) return 'MEDIUM'
|
||||||
|
|
||||||
|
return 'HIGH'
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate AI reasoning for leverage decision
|
||||||
|
*/
|
||||||
|
private static generateLeverageReasoning(
|
||||||
|
finalLeverage: number,
|
||||||
|
maxSafeLeverage: number,
|
||||||
|
maxPlatformLeverage: number,
|
||||||
|
liquidationPrice: number,
|
||||||
|
stopLossPrice: number,
|
||||||
|
useFullBalance: boolean,
|
||||||
|
side: 'long' | 'short'
|
||||||
|
): string {
|
||||||
|
|
||||||
|
const reasons = []
|
||||||
|
|
||||||
|
// Balance strategy reasoning
|
||||||
|
if (useFullBalance) {
|
||||||
|
reasons.push("Account <$1k: Using 100% available balance for maximum growth")
|
||||||
|
} else {
|
||||||
|
reasons.push("Account >$1k: Using 50% balance for controlled risk")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Leverage limitation reasoning
|
||||||
|
if (finalLeverage === maxSafeLeverage) {
|
||||||
|
reasons.push(`Max safe leverage ${finalLeverage.toFixed(1)}x maintains liquidation safely beyond stop loss`)
|
||||||
|
} else if (finalLeverage === maxPlatformLeverage) {
|
||||||
|
reasons.push(`Platform limit ${maxPlatformLeverage}x reached (could use ${maxSafeLeverage.toFixed(1)}x safely)`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Liquidation safety reasoning
|
||||||
|
const liquidationBuffer = side === 'long'
|
||||||
|
? (stopLossPrice - liquidationPrice) / stopLossPrice * 100
|
||||||
|
: (liquidationPrice - stopLossPrice) / stopLossPrice * 100
|
||||||
|
|
||||||
|
reasons.push(`Liquidation $${liquidationPrice.toFixed(4)} is ${liquidationBuffer.toFixed(1)}% beyond stop loss`)
|
||||||
|
|
||||||
|
return reasons.join('. ')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AILeverageCalculator
|
||||||
@@ -7,7 +7,8 @@ import aggressiveCleanup from './aggressive-cleanup'
|
|||||||
import { analysisCompletionFlag } from './analysis-completion-flag'
|
import { analysisCompletionFlag } from './analysis-completion-flag'
|
||||||
import priceMonitorService from './price-monitor'
|
import priceMonitorService from './price-monitor'
|
||||||
|
|
||||||
const prisma = new PrismaClient()
|
import prisma from '../lib/prisma'
|
||||||
|
import AILeverageCalculator from './ai-leverage-calculator'
|
||||||
|
|
||||||
export interface AutomationConfig {
|
export interface AutomationConfig {
|
||||||
userId: string
|
userId: string
|
||||||
@@ -634,13 +635,17 @@ ${validResults.map(r => `• ${r.timeframe}: ${r.analysis?.recommendation} (${r.
|
|||||||
console.log('📈 BUY signal detected')
|
console.log('📈 BUY signal detected')
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate position size based on risk percentage
|
// Calculate AI-driven position size with optimal leverage
|
||||||
const positionSize = await this.calculatePositionSize(analysis)
|
const positionResult = await this.calculatePositionSize(analysis)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
direction: analysis.recommendation,
|
direction: analysis.recommendation,
|
||||||
confidence: analysis.confidence,
|
confidence: analysis.confidence,
|
||||||
positionSize,
|
positionSize: positionResult.tokenAmount,
|
||||||
|
leverageUsed: positionResult.leverageUsed,
|
||||||
|
marginRequired: positionResult.marginRequired,
|
||||||
|
liquidationPrice: positionResult.liquidationPrice,
|
||||||
|
riskAssessment: positionResult.riskAssessment,
|
||||||
stopLoss: this.calculateStopLoss(analysis),
|
stopLoss: this.calculateStopLoss(analysis),
|
||||||
takeProfit: this.calculateTakeProfit(analysis),
|
takeProfit: this.calculateTakeProfit(analysis),
|
||||||
marketSentiment: analysis.marketSentiment,
|
marketSentiment: analysis.marketSentiment,
|
||||||
@@ -687,39 +692,92 @@ ${validResults.map(r => `• ${r.timeframe}: ${r.analysis?.recommendation} (${r.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async calculatePositionSize(analysis: any): Promise<number> {
|
private async calculatePositionSize(analysis: any): Promise<{
|
||||||
const baseAmount = this.config!.tradingAmount // This is the USD amount to invest
|
tokenAmount: number
|
||||||
const riskAdjustment = this.config!.riskPercentage / 100
|
leverageUsed: number
|
||||||
const confidenceAdjustment = analysis.confidence / 100
|
marginRequired: number
|
||||||
|
liquidationPrice: number
|
||||||
|
riskAssessment: string
|
||||||
|
}> {
|
||||||
|
console.log('🧠 AI Position Sizing with Dynamic Leverage Calculation...')
|
||||||
|
|
||||||
// ✅ ENHANCED: Handle both BUY and SELL position sizing
|
// ✅ ENHANCED: Handle SELL positions with AI leverage for shorting
|
||||||
if (analysis.recommendation === 'SELL') {
|
if (analysis.recommendation === 'SELL') {
|
||||||
// For SELL orders, calculate how much SOL to sell based on current holdings
|
return await this.calculateSellPositionWithLeverage(analysis)
|
||||||
return await this.calculateSellAmount(analysis)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// For BUY orders, calculate USD amount to invest
|
// Get account balance
|
||||||
const usdAmount = baseAmount * riskAdjustment * confidenceAdjustment
|
const balanceResponse = await fetch(`${process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000'}/api/drift/balance`)
|
||||||
|
const balanceData = await balanceResponse.json()
|
||||||
|
|
||||||
// Get current price to convert USD to token amount
|
if (!balanceData.success) {
|
||||||
|
throw new Error('Could not fetch account balance for position sizing')
|
||||||
|
}
|
||||||
|
|
||||||
|
const accountValue = balanceData.accountValue || balanceData.totalCollateral
|
||||||
|
const availableBalance = balanceData.availableBalance
|
||||||
|
|
||||||
|
console.log(`💰 Account Status: Value=$${accountValue.toFixed(2)}, Available=$${availableBalance.toFixed(2)}`)
|
||||||
|
|
||||||
|
// Get current price for entry
|
||||||
let currentPrice = analysis.entry?.price || analysis.currentPrice
|
let currentPrice = analysis.entry?.price || analysis.currentPrice
|
||||||
|
|
||||||
if (!currentPrice) {
|
if (!currentPrice) {
|
||||||
try {
|
try {
|
||||||
const { default: PriceFetcher } = await import('./price-fetcher')
|
const { default: PriceFetcher } = await import('./price-fetcher')
|
||||||
currentPrice = await PriceFetcher.getCurrentPrice(this.config?.symbol || 'SOLUSD')
|
currentPrice = await PriceFetcher.getCurrentPrice(this.config?.symbol || 'SOLUSD')
|
||||||
console.log(`📊 Using current ${this.config?.symbol || 'SOLUSD'} price for position size: $${currentPrice}`)
|
console.log(`📊 Using current ${this.config?.symbol || 'SOLUSD'} price: $${currentPrice}`)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching price for position size, using fallback:', error)
|
console.error('Error fetching price for position sizing, using fallback:', error)
|
||||||
currentPrice = this.config?.symbol === 'SOLUSD' ? 189 : 100
|
currentPrice = this.config?.symbol === 'SOLUSD' ? 189 : 100
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calculate stop loss price from analysis
|
||||||
|
const stopLossPercent = this.calculateAIStopLoss(analysis) / 100
|
||||||
|
const direction = analysis.recommendation === 'BUY' ? 'long' : 'short'
|
||||||
|
|
||||||
// Calculate token amount: USD investment / token price
|
let stopLossPrice: number
|
||||||
const tokenAmount = usdAmount / currentPrice
|
if (direction === 'long') {
|
||||||
console.log(`💰 BUY Position calculation: $${usdAmount} ÷ $${currentPrice} = ${tokenAmount.toFixed(4)} tokens`)
|
stopLossPrice = currentPrice * (1 - stopLossPercent)
|
||||||
|
} else {
|
||||||
return tokenAmount
|
stopLossPrice = currentPrice * (1 + stopLossPercent)
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`🎯 Position Parameters: Entry=$${currentPrice}, StopLoss=$${stopLossPrice.toFixed(4)}, Direction=${direction}`)
|
||||||
|
|
||||||
|
// Use AI Leverage Calculator for optimal leverage
|
||||||
|
const leverageResult = AILeverageCalculator.calculateOptimalLeverage({
|
||||||
|
accountValue,
|
||||||
|
availableBalance,
|
||||||
|
entryPrice: currentPrice,
|
||||||
|
stopLossPrice,
|
||||||
|
side: direction,
|
||||||
|
maxLeverageAllowed: this.config!.maxLeverage || 20, // Platform max leverage
|
||||||
|
safetyBuffer: 0.10 // 10% safety buffer between liquidation and stop loss
|
||||||
|
})
|
||||||
|
|
||||||
|
// Calculate final position size
|
||||||
|
const baseAmount = accountValue < 1000 ? availableBalance : availableBalance * 0.5
|
||||||
|
const leveragedAmount = baseAmount * leverageResult.recommendedLeverage
|
||||||
|
const tokenAmount = leveragedAmount / currentPrice
|
||||||
|
|
||||||
|
console.log(`<EFBFBD> AI Position Result:`, {
|
||||||
|
baseAmount: `$${baseAmount.toFixed(2)}`,
|
||||||
|
leverage: `${leverageResult.recommendedLeverage.toFixed(1)}x`,
|
||||||
|
leveragedAmount: `$${leveragedAmount.toFixed(2)}`,
|
||||||
|
tokenAmount: tokenAmount.toFixed(4),
|
||||||
|
riskLevel: leverageResult.riskAssessment,
|
||||||
|
reasoning: leverageResult.reasoning
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
tokenAmount,
|
||||||
|
leverageUsed: leverageResult.recommendedLeverage,
|
||||||
|
marginRequired: leverageResult.marginRequired,
|
||||||
|
liquidationPrice: leverageResult.liquidationPrice,
|
||||||
|
riskAssessment: leverageResult.riskAssessment
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ NEW: Calculate SOL amount to sell for SELL orders
|
// ✅ NEW: Calculate SOL amount to sell for SELL orders
|
||||||
@@ -756,6 +814,82 @@ ${validResults.map(r => `• ${r.timeframe}: ${r.analysis?.recommendation} (${r.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ✅ NEW: Calculate leveraged short position for SELL orders
|
||||||
|
private async calculateSellPositionWithLeverage(analysis: any): Promise<{
|
||||||
|
tokenAmount: number
|
||||||
|
leverageUsed: number
|
||||||
|
marginRequired: number
|
||||||
|
liquidationPrice: number
|
||||||
|
riskAssessment: string
|
||||||
|
}> {
|
||||||
|
try {
|
||||||
|
console.log('📉 Calculating SELL position with AI leverage...')
|
||||||
|
|
||||||
|
// Get account balance for leverage calculation
|
||||||
|
const balanceResponse = await fetch(`${process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000'}/api/drift/balance`)
|
||||||
|
const balanceData = await balanceResponse.json()
|
||||||
|
|
||||||
|
const accountValue = balanceData.accountValue || balanceData.totalCollateral
|
||||||
|
const availableBalance = balanceData.availableBalance
|
||||||
|
|
||||||
|
// Get current price
|
||||||
|
let currentPrice = analysis.entry?.price || analysis.currentPrice
|
||||||
|
if (!currentPrice) {
|
||||||
|
const { default: PriceFetcher } = await import('./price-fetcher')
|
||||||
|
currentPrice = await PriceFetcher.getCurrentPrice(this.config?.symbol || 'SOLUSD')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate stop loss for short position (above entry price)
|
||||||
|
const stopLossPercent = this.calculateAIStopLoss(analysis) / 100
|
||||||
|
const stopLossPrice = currentPrice * (1 + stopLossPercent)
|
||||||
|
|
||||||
|
console.log(`🎯 SHORT Position Parameters: Entry=$${currentPrice}, StopLoss=$${stopLossPrice.toFixed(4)}`)
|
||||||
|
|
||||||
|
// Use AI leverage for short position
|
||||||
|
const leverageResult = AILeverageCalculator.calculateOptimalLeverage({
|
||||||
|
accountValue,
|
||||||
|
availableBalance,
|
||||||
|
entryPrice: currentPrice,
|
||||||
|
stopLossPrice,
|
||||||
|
side: 'short',
|
||||||
|
maxLeverageAllowed: this.config!.maxLeverage || 20,
|
||||||
|
safetyBuffer: 0.10
|
||||||
|
})
|
||||||
|
|
||||||
|
// Calculate leveraged short amount
|
||||||
|
const baseAmount = accountValue < 1000 ? availableBalance : availableBalance * 0.5
|
||||||
|
const leveragedAmount = baseAmount * leverageResult.recommendedLeverage
|
||||||
|
const tokenAmount = leveragedAmount / currentPrice
|
||||||
|
|
||||||
|
console.log(`📉 SELL Position with AI Leverage:`, {
|
||||||
|
baseAmount: `$${baseAmount.toFixed(2)}`,
|
||||||
|
leverage: `${leverageResult.recommendedLeverage.toFixed(1)}x`,
|
||||||
|
leveragedAmount: `$${leveragedAmount.toFixed(2)}`,
|
||||||
|
tokenAmount: tokenAmount.toFixed(4),
|
||||||
|
riskLevel: leverageResult.riskAssessment,
|
||||||
|
reasoning: leverageResult.reasoning
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
tokenAmount,
|
||||||
|
leverageUsed: leverageResult.recommendedLeverage,
|
||||||
|
marginRequired: leverageResult.marginRequired,
|
||||||
|
liquidationPrice: leverageResult.liquidationPrice,
|
||||||
|
riskAssessment: leverageResult.riskAssessment
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error calculating SELL position with leverage:', error)
|
||||||
|
return {
|
||||||
|
tokenAmount: 0.01, // Fallback small amount
|
||||||
|
leverageUsed: 1,
|
||||||
|
marginRequired: 0,
|
||||||
|
liquidationPrice: 0,
|
||||||
|
riskAssessment: 'HIGH'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private calculateStopLoss(analysis: any): number {
|
private calculateStopLoss(analysis: any): number {
|
||||||
// ✅ AI-FIRST: Use AI analysis stopLoss if available
|
// ✅ AI-FIRST: Use AI analysis stopLoss if available
|
||||||
if (analysis.stopLoss?.price) {
|
if (analysis.stopLoss?.price) {
|
||||||
@@ -929,8 +1063,10 @@ ${validResults.map(r => `• ${r.timeframe}: ${r.analysis?.recommendation} (${r.
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async executeLiveTrade(decision: any): Promise<any> {
|
private async executeLiveTrade(decision: any): Promise<any> {
|
||||||
// Execute real trade via Drift Protocol
|
// Execute real trade via Drift Protocol with AI-calculated leverage
|
||||||
console.log(`🌊 Executing Drift trade: ${decision.direction} ${this.config!.symbol}`)
|
console.log(`🌊 Executing Drift trade: ${decision.direction} ${this.config!.symbol}`)
|
||||||
|
console.log(`🧠 AI Leverage: ${decision.leverageUsed.toFixed(1)}x (Risk: ${decision.riskAssessment})`)
|
||||||
|
console.log(`💀 Liquidation Price: $${decision.liquidationPrice.toFixed(4)}`)
|
||||||
|
|
||||||
// Calculate AI-generated stop loss and take profit from analysis
|
// Calculate AI-generated stop loss and take profit from analysis
|
||||||
const stopLossPercent = decision.stopLoss || this.calculateAIStopLoss(decision)
|
const stopLossPercent = decision.stopLoss || this.calculateAIStopLoss(decision)
|
||||||
@@ -950,12 +1086,19 @@ ${validResults.map(r => `• ${r.timeframe}: ${r.analysis?.recommendation} (${r.
|
|||||||
symbol: this.config!.symbol,
|
symbol: this.config!.symbol,
|
||||||
amount: this.config!.tradingAmount,
|
amount: this.config!.tradingAmount,
|
||||||
side: decision.direction.toLowerCase(),
|
side: decision.direction.toLowerCase(),
|
||||||
leverage: this.config!.maxLeverage || 2,
|
leverage: decision.leverageUsed || this.config!.maxLeverage || 2, // Use AI-calculated leverage
|
||||||
stopLoss: true,
|
stopLoss: true,
|
||||||
takeProfit: true,
|
takeProfit: true,
|
||||||
stopLossPercent: stopLossPercent,
|
stopLossPercent: stopLossPercent,
|
||||||
takeProfitPercent: takeProfitPercent,
|
takeProfitPercent: takeProfitPercent,
|
||||||
mode: this.config!.mode || 'SIMULATION'
|
mode: this.config!.mode || 'SIMULATION',
|
||||||
|
// Include AI leverage details for logging
|
||||||
|
aiLeverageDetails: {
|
||||||
|
calculatedLeverage: decision.leverageUsed,
|
||||||
|
liquidationPrice: decision.liquidationPrice,
|
||||||
|
riskAssessment: decision.riskAssessment,
|
||||||
|
marginRequired: decision.marginRequired
|
||||||
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -970,7 +1113,9 @@ ${validResults.map(r => `• ${r.timeframe}: ${r.analysis?.recommendation} (${r.
|
|||||||
direction: decision.direction,
|
direction: decision.direction,
|
||||||
status: 'COMPLETED',
|
status: 'COMPLETED',
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
leverage: tradeResult.leverageUsed || this.config!.maxLeverage,
|
leverage: decision.leverageUsed || tradeResult.leverageUsed || this.config!.maxLeverage,
|
||||||
|
liquidationPrice: decision.liquidationPrice,
|
||||||
|
riskAssessment: decision.riskAssessment,
|
||||||
stopLoss: stopLossPercent,
|
stopLoss: stopLossPercent,
|
||||||
takeProfit: takeProfitPercent,
|
takeProfit: takeProfitPercent,
|
||||||
tradingAmount: this.config!.tradingAmount,
|
tradingAmount: this.config!.tradingAmount,
|
||||||
@@ -1015,11 +1160,22 @@ ${validResults.map(r => `• ${r.timeframe}: ${r.analysis?.recommendation} (${r.
|
|||||||
confidence: decision.confidence,
|
confidence: decision.confidence,
|
||||||
marketSentiment: decision.marketSentiment,
|
marketSentiment: decision.marketSentiment,
|
||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
|
// Add AI leverage information
|
||||||
|
leverage: result.leverage || decision.leverageUsed,
|
||||||
// Add Drift-specific fields for live trades
|
// Add Drift-specific fields for live trades
|
||||||
...(this.config!.mode === 'LIVE' && result.tradingAmount && {
|
...(this.config!.mode === 'LIVE' && result.tradingAmount && {
|
||||||
realTradingAmount: this.config!.tradingAmount,
|
realTradingAmount: this.config!.tradingAmount,
|
||||||
leverage: result.leverage,
|
|
||||||
driftTxId: result.transactionId
|
driftTxId: result.transactionId
|
||||||
|
}),
|
||||||
|
// Add AI leverage details in metadata
|
||||||
|
metadata: JSON.stringify({
|
||||||
|
aiLeverage: {
|
||||||
|
calculatedLeverage: decision.leverageUsed,
|
||||||
|
liquidationPrice: decision.liquidationPrice,
|
||||||
|
riskAssessment: decision.riskAssessment,
|
||||||
|
marginRequired: decision.marginRequired,
|
||||||
|
balanceStrategy: result.accountValue < 1000 ? 'AGGRESSIVE_100%' : 'CONSERVATIVE_50%'
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user