Fix automation v2 timeframe selection and SELL signal execution
- Fixed timeframe selection to use user-selected timeframes instead of hardcoded values - Added selectedTimeframes property to AutomationConfig interface - Added maxDailyTrades property to AutomationConfig interface - Removed Jupiter DEX blocking logic that prevented SELL signals from opening SHORT positions - Fixed SELL signals to properly execute SHORT positions on Drift Protocol - Updated automation test route with missing properties (selectedTimeframes, maxDailyTrades, dexProvider) - Added debug logging to automation v2 page for better troubleshooting - Added test click button for UI interaction debugging - Resolved TypeScript compilation errors in automation service - Ensured automation v2 interface is fully functional and responsive These changes enable: - Multi-timeframe analysis with user-selected timeframes - Proper SHORT position execution on SELL signals - Improved UI reliability and debugging capabilities - Full Drift Protocol perpetual futures trading support
This commit is contained in:
@@ -11,12 +11,14 @@ export async function GET(request: NextRequest) {
|
|||||||
mode: 'SIMULATION' as const,
|
mode: 'SIMULATION' as const,
|
||||||
symbol: 'SOLUSD',
|
symbol: 'SOLUSD',
|
||||||
timeframe: '1h',
|
timeframe: '1h',
|
||||||
|
selectedTimeframes: ['1h'],
|
||||||
tradingAmount: 10, // $10 for simulation
|
tradingAmount: 10, // $10 for simulation
|
||||||
maxLeverage: 2,
|
maxLeverage: 2,
|
||||||
stopLossPercent: 2,
|
stopLossPercent: 2,
|
||||||
takeProfitPercent: 6,
|
takeProfitPercent: 6,
|
||||||
maxDailyTrades: 5,
|
maxDailyTrades: 5,
|
||||||
riskPercentage: 1
|
riskPercentage: 1,
|
||||||
|
dexProvider: 'DRIFT' as const
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('📋 Config:', testConfig)
|
console.log('📋 Config:', testConfig)
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ export default function AutomationPageV2() {
|
|||||||
try {
|
try {
|
||||||
const response = await fetch('/api/automation/status')
|
const response = await fetch('/api/automation/status')
|
||||||
const data = await response.json()
|
const data = await response.json()
|
||||||
|
console.log('Status fetched:', data) // Debug log
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
setStatus(data.status)
|
setStatus(data.status)
|
||||||
}
|
}
|
||||||
@@ -90,6 +91,7 @@ export default function AutomationPageV2() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleStart = async () => {
|
const handleStart = async () => {
|
||||||
|
console.log('Start button clicked') // Debug log
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
try {
|
try {
|
||||||
// Ensure we have selectedTimeframes before starting
|
// Ensure we have selectedTimeframes before starting
|
||||||
@@ -126,12 +128,14 @@ export default function AutomationPageV2() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleStop = async () => {
|
const handleStop = async () => {
|
||||||
|
console.log('Stop button clicked') // Debug log
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/api/automation/stop', {
|
const response = await fetch('/api/automation/stop', {
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
})
|
})
|
||||||
const data = await response.json()
|
const data = await response.json()
|
||||||
|
console.log('Stop response:', data) // Debug log
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
fetchStatus()
|
fetchStatus()
|
||||||
} else {
|
} else {
|
||||||
@@ -157,6 +161,12 @@ export default function AutomationPageV2() {
|
|||||||
<p className="text-gray-400 mt-1">Drift Protocol - Multi-Timeframe Analysis</p>
|
<p className="text-gray-400 mt-1">Drift Protocol - Multi-Timeframe Analysis</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex space-x-4">
|
<div className="flex space-x-4">
|
||||||
|
<button
|
||||||
|
onClick={() => console.log('TEST BUTTON CLICKED')}
|
||||||
|
className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700"
|
||||||
|
>
|
||||||
|
Test Click
|
||||||
|
</button>
|
||||||
{status?.isActive ? (
|
{status?.isActive ? (
|
||||||
<button
|
<button
|
||||||
onClick={handleStop}
|
onClick={handleStop}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ export interface AutomationConfig {
|
|||||||
mode: 'SIMULATION' | 'LIVE'
|
mode: 'SIMULATION' | 'LIVE'
|
||||||
symbol: string
|
symbol: string
|
||||||
timeframe: string
|
timeframe: string
|
||||||
|
selectedTimeframes: string[] // Multi-timeframe support
|
||||||
tradingAmount: number
|
tradingAmount: number
|
||||||
maxLeverage: number
|
maxLeverage: number
|
||||||
stopLossPercent: number
|
stopLossPercent: number
|
||||||
@@ -62,6 +63,9 @@ export class AutomationService {
|
|||||||
this.isRunning = true
|
this.isRunning = true
|
||||||
|
|
||||||
console.log(`🤖 Starting automation for ${config.symbol} ${config.timeframe} in ${config.mode} mode`)
|
console.log(`🤖 Starting automation for ${config.symbol} ${config.timeframe} in ${config.mode} mode`)
|
||||||
|
console.log(`📊 Using timeframes: ${config.selectedTimeframes?.join(", ") || "default fallback"}`)
|
||||||
|
console.log(`📊 Timeframes array:`, config.selectedTimeframes)
|
||||||
|
console.log(`🔧 Full config:`, JSON.stringify(config, null, 2))
|
||||||
|
|
||||||
// Ensure user exists in database
|
// Ensure user exists in database
|
||||||
await prisma.user.upsert({
|
await prisma.user.upsert({
|
||||||
@@ -95,6 +99,7 @@ export class AutomationService {
|
|||||||
timeframe: config.timeframe,
|
timeframe: config.timeframe,
|
||||||
settings: {
|
settings: {
|
||||||
tradingAmount: config.tradingAmount,
|
tradingAmount: config.tradingAmount,
|
||||||
|
selectedTimeframes: config.selectedTimeframes,
|
||||||
maxLeverage: config.maxLeverage,
|
maxLeverage: config.maxLeverage,
|
||||||
stopLossPercent: config.stopLossPercent,
|
stopLossPercent: config.stopLossPercent,
|
||||||
takeProfitPercent: config.takeProfitPercent,
|
takeProfitPercent: config.takeProfitPercent,
|
||||||
@@ -274,7 +279,7 @@ export class AutomationService {
|
|||||||
progressTracker.updateStep(sessionId, 'init', 'active', 'Starting multi-timeframe analysis...')
|
progressTracker.updateStep(sessionId, 'init', 'active', 'Starting multi-timeframe analysis...')
|
||||||
|
|
||||||
// Multi-timeframe analysis: 15m, 1h, 2h, 4h
|
// Multi-timeframe analysis: 15m, 1h, 2h, 4h
|
||||||
const timeframes = ['15', '1h', '2h', '4h']
|
const timeframes = this.config!.selectedTimeframes && this.config!.selectedTimeframes.length > 0 ? this.config!.selectedTimeframes : ["15", "60", "120", "240"]
|
||||||
const symbol = this.config!.symbol
|
const symbol = this.config!.symbol
|
||||||
|
|
||||||
console.log(`🔍 Analyzing ${symbol} across timeframes: ${timeframes.join(', ')} with AI + DIY layouts`)
|
console.log(`🔍 Analyzing ${symbol} across timeframes: ${timeframes.join(', ')} with AI + DIY layouts`)
|
||||||
@@ -593,17 +598,12 @@ ${validResults.map(r => `• ${r.timeframe}: ${r.analysis?.recommendation} (${r.
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ ENHANCED: Support both BUY and SELL signals
|
|
||||||
if (analysis.recommendation === 'SELL') {
|
// Log the trading signal
|
||||||
// Check if we have SOL position to sell
|
if (analysis.recommendation === "SELL") {
|
||||||
const hasPosition = await this.checkCurrentPosition()
|
console.log("📉 SELL signal detected - Opening SHORT position")
|
||||||
if (!hasPosition) {
|
} else if (analysis.recommendation === "BUY") {
|
||||||
console.log('📊 SELL signal but no SOL position to sell - skipping')
|
console.log("📈 BUY signal detected - Opening LONG position")
|
||||||
return null
|
|
||||||
}
|
|
||||||
console.log('📉 SELL signal detected with existing SOL position')
|
|
||||||
} else if (analysis.recommendation === 'BUY') {
|
|
||||||
console.log('📈 BUY signal detected')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate position size based on risk percentage
|
// Calculate position size based on risk percentage
|
||||||
@@ -625,40 +625,6 @@ ${validResults.map(r => `• ${r.timeframe}: ${r.analysis?.recommendation} (${r.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ NEW: Check if we have SOL position available to sell
|
|
||||||
private async checkCurrentPosition(): Promise<boolean> {
|
|
||||||
try {
|
|
||||||
// Check recent trades to see current position
|
|
||||||
const recentTrades = await prisma.trade.findMany({
|
|
||||||
where: {
|
|
||||||
userId: this.config!.userId,
|
|
||||||
symbol: this.config!.symbol,
|
|
||||||
status: 'OPEN'
|
|
||||||
},
|
|
||||||
orderBy: { createdAt: 'desc' },
|
|
||||||
take: 5
|
|
||||||
})
|
|
||||||
|
|
||||||
// Count open positions
|
|
||||||
let netPosition = 0
|
|
||||||
for (const trade of recentTrades) {
|
|
||||||
if (trade.side === 'BUY') {
|
|
||||||
netPosition += trade.amount
|
|
||||||
} else if (trade.side === 'SELL') {
|
|
||||||
netPosition -= trade.amount
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`🔍 Current SOL position: ${netPosition.toFixed(4)} SOL`)
|
|
||||||
return netPosition > 0.001 // Have at least 0.001 SOL to sell
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error('❌ Error checking current position:', error)
|
|
||||||
// If we can't check, default to allowing the trade (fail-safe)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async calculatePositionSize(analysis: any): Promise<number> {
|
private async calculatePositionSize(analysis: any): Promise<number> {
|
||||||
const baseAmount = this.config!.tradingAmount // This is the USD amount to invest
|
const baseAmount = this.config!.tradingAmount // This is the USD amount to invest
|
||||||
const riskAdjustment = this.config!.riskPercentage / 100
|
const riskAdjustment = this.config!.riskPercentage / 100
|
||||||
@@ -1106,6 +1072,7 @@ ${validResults.map(r => `• ${r.timeframe}: ${r.analysis?.recommendation} (${r.
|
|||||||
mode: session.mode,
|
mode: session.mode,
|
||||||
symbol: session.symbol,
|
symbol: session.symbol,
|
||||||
timeframe: session.timeframe,
|
timeframe: session.timeframe,
|
||||||
|
selectedTimeframes: settings.selectedTimeframes || ["60", "240"], // Default fallback
|
||||||
tradingAmount: settings.tradingAmount || 100,
|
tradingAmount: settings.tradingAmount || 100,
|
||||||
maxLeverage: settings.maxLeverage || 3,
|
maxLeverage: settings.maxLeverage || 3,
|
||||||
stopLossPercent: settings.stopLossPercent || 2,
|
stopLossPercent: settings.stopLossPercent || 2,
|
||||||
|
|||||||
@@ -10,10 +10,12 @@ export interface AutomationConfig {
|
|||||||
mode: 'SIMULATION' | 'LIVE'
|
mode: 'SIMULATION' | 'LIVE'
|
||||||
symbol: string
|
symbol: string
|
||||||
timeframe: string
|
timeframe: string
|
||||||
|
selectedTimeframes: string[] // Multi-timeframe support
|
||||||
tradingAmount: number
|
tradingAmount: number
|
||||||
maxLeverage: number
|
maxLeverage: number
|
||||||
stopLossPercent: number
|
stopLossPercent: number
|
||||||
takeProfitPercent: number
|
takeProfitPercent: number
|
||||||
|
maxDailyTrades: number
|
||||||
riskPercentage: number
|
riskPercentage: number
|
||||||
dexProvider: 'JUPITER' | 'DRIFT'
|
dexProvider: 'JUPITER' | 'DRIFT'
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user