feat: implement strategy-aware analysis intervals and remove manual leverage controls
- Remove manual leverage field from automation v2 page since AI now handles leverage automatically - Fix scalping strategy analysis intervals from 60 minutes to 2 minutes for proper high-frequency trading - Implement intelligent interval detection based on selected timeframes: * Scalping: 2 minutes (5m, 3m, or multiple short timeframes) * Day trading: 5 minutes (1h, 2h timeframes) * Swing trading: 15 minutes (4h, daily timeframes) - Fix Drift SDK API calls: replace getTotalPerpPositionValue() with getFreeCollateral() - Clean up UI by removing manual controls since AI systems handle optimization - Fix syntax errors in automation service and balance API - Ensure proper margin calculations using correct Drift Protocol methods Tested: Scalping strategy now correctly analyzes every 2 minutes instead of 60 minutes
This commit is contained in:
@@ -17,7 +17,6 @@ export async function POST(request) {
|
||||
// Map tradeSize to tradingAmount
|
||||
tradingAmount: config.tradeSize || config.tradingAmount,
|
||||
// Set defaults for missing fields
|
||||
maxLeverage: config.maxLeverage || 2,
|
||||
maxDailyTrades: config.maxDailyTrades || 5,
|
||||
dexProvider: config.dexProvider || 'DRIFT',
|
||||
selectedTimeframes: config.selectedTimeframes || [config.timeframe || '1h']
|
||||
|
||||
@@ -87,16 +87,19 @@ export async function GET() {
|
||||
unrealizedPnl = 0 // Default to 0 if we can't calculate
|
||||
}
|
||||
|
||||
let freeCollateralFromDrift = 0
|
||||
try {
|
||||
// Calculate margin requirement using Drift's method
|
||||
marginRequirement = await driftClient.getUser().getTotalPerpPositionValue() / 1e6 * 0.1 // 10% margin
|
||||
// Calculate margin requirement using proper Drift SDK methods
|
||||
freeCollateralFromDrift = await driftClient.getUser().getFreeCollateral() / 1e6 // Convert to USDC
|
||||
marginRequirement = Math.max(0, totalCollateral - freeCollateralFromDrift) // Used collateral
|
||||
} catch (marginError) {
|
||||
console.warn('⚠️ Could not get margin requirement, calculating manually:', marginError.message)
|
||||
marginRequirement = 0 // Default to 0 if we can't calculate
|
||||
}
|
||||
|
||||
// Calculate free collateral and other derived values
|
||||
const freeCollateral = totalCollateral - marginRequirement + unrealizedPnl
|
||||
// Use Drift's free collateral if available, otherwise calculate manually
|
||||
const freeCollateral = freeCollateralFromDrift > 0 ? freeCollateralFromDrift : Math.max(0, totalCollateral - marginRequirement + unrealizedPnl)
|
||||
const accountValue = totalCollateral + unrealizedPnl
|
||||
const leverage = marginRequirement > 0 ? (marginRequirement / accountValue) : 0
|
||||
const availableBalance = Math.max(0, freeCollateral)
|
||||
|
||||
@@ -21,7 +21,6 @@ export default function AutomationPageV2() {
|
||||
selectedTimeframes: ['60'], // Multi-timeframe support
|
||||
tradingAmount: 100,
|
||||
balancePercentage: 50, // Default to 50% of available balance
|
||||
maxLeverage: 5
|
||||
// stopLossPercent and takeProfitPercent removed - AI calculates these automatically
|
||||
})
|
||||
|
||||
@@ -268,22 +267,6 @@ export default function AutomationPageV2() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-3">
|
||||
<label className="block text-sm font-bold text-purple-400">Leverage</label>
|
||||
<select
|
||||
className="w-full p-3 bg-gray-700 border border-gray-600 rounded-lg text-white focus:border-purple-400"
|
||||
value={config.maxLeverage}
|
||||
onChange={(e) => setConfig({...config, maxLeverage: parseInt(e.target.value)})}
|
||||
disabled={status?.isActive}
|
||||
>
|
||||
<option value="1">1x - Spot</option>
|
||||
<option value="2">2x</option>
|
||||
<option value="3">3x</option>
|
||||
<option value="5">5x</option>
|
||||
<option value="10">10x</option>
|
||||
<option value="20">20x</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Symbol and Position Size */}
|
||||
@@ -336,11 +319,6 @@ export default function AutomationPageV2() {
|
||||
<span>50%</span>
|
||||
<span>100%</span>
|
||||
</div>
|
||||
{balance && config.maxLeverage > 1 && (
|
||||
<p className="text-xs text-green-400 mt-1">
|
||||
With {config.maxLeverage}x leverage: ${(config.tradingAmount * config.maxLeverage).toFixed(2)} position exposure
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -524,10 +502,6 @@ export default function AutomationPageV2() {
|
||||
{config.selectedTimeframes.map(tf => timeframes.find(t => t.value === tf)?.label).filter(Boolean).join(', ')}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
<span className="text-gray-300">Leverage:</span>
|
||||
<span className="text-yellow-400 font-semibold">{config.maxLeverage}x</span>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<p className="text-gray-400">Loading bot status...</p>
|
||||
@@ -653,7 +627,33 @@ export default function AutomationPageV2() {
|
||||
></div>
|
||||
</div>
|
||||
<div className="text-xs text-gray-400 text-center">
|
||||
Analysis Interval: {Math.floor((status.analysisInterval || 0) / 60)}m
|
||||
Analysis Interval: {(() => {
|
||||
const intervalSec = status.analysisInterval || 0
|
||||
const intervalMin = Math.floor(intervalSec / 60)
|
||||
|
||||
// Determine strategy type for display
|
||||
if (status.selectedTimeframes) {
|
||||
const timeframes = status.selectedTimeframes
|
||||
const isScalping = timeframes.includes('5') || timeframes.includes('3') ||
|
||||
(timeframes.length > 1 && timeframes.every(tf => ['1', '3', '5', '15', '30'].includes(tf)))
|
||||
|
||||
if (isScalping) {
|
||||
return '2m (Scalping Mode)'
|
||||
}
|
||||
|
||||
const isDayTrading = timeframes.includes('60') || timeframes.includes('120')
|
||||
if (isDayTrading) {
|
||||
return '5m (Day Trading Mode)'
|
||||
}
|
||||
|
||||
const isSwingTrading = timeframes.includes('240') || timeframes.includes('D')
|
||||
if (isSwingTrading) {
|
||||
return '15m (Swing Trading Mode)'
|
||||
}
|
||||
}
|
||||
|
||||
return `${intervalMin}m`
|
||||
})()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -168,6 +168,35 @@ export class AutomationService {
|
||||
}
|
||||
|
||||
private getIntervalFromTimeframe(timeframe: string): number {
|
||||
// Check if this is a scalping strategy (multiple short timeframes)
|
||||
if (this.config?.selectedTimeframes) {
|
||||
const timeframes = this.config.selectedTimeframes
|
||||
const isScalping = timeframes.includes('5') || timeframes.includes('3') || (timeframes.length > 1 && timeframes.every(tf => ['1', '3', '5', '15', '30'].includes(tf)))
|
||||
if (isScalping) {
|
||||
console.log('🎯 Scalping strategy detected - using frequent analysis (2-3 minutes)')
|
||||
return 2 * 60 * 1000 // 2 minutes for scalping
|
||||
}
|
||||
|
||||
// Day trading strategy (short-medium timeframes)
|
||||
const isDayTrading = timeframes.includes('60') || timeframes.includes('120') ||
|
||||
timeframes.some(tf => ['30', '60', '120'].includes(tf))
|
||||
|
||||
if (isDayTrading) {
|
||||
console.log('⚡ Day trading strategy detected - using moderate analysis (5-10 minutes)')
|
||||
return 5 * 60 * 1000 // 5 minutes for day trading
|
||||
}
|
||||
|
||||
// Swing trading (longer timeframes)
|
||||
const isSwingTrading = timeframes.includes('240') || timeframes.includes('D') ||
|
||||
timeframes.some(tf => ['240', '480', 'D', '1d'].includes(tf))
|
||||
|
||||
if (isSwingTrading) {
|
||||
console.log('🎯 Swing trading strategy detected - using standard analysis (15-30 minutes)')
|
||||
return 15 * 60 * 1000 // 15 minutes for swing trading
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to timeframe-based intervals
|
||||
const intervals: { [key: string]: number } = {
|
||||
'1m': 60 * 1000,
|
||||
'3m': 3 * 60 * 1000,
|
||||
|
||||
Reference in New Issue
Block a user