fix: v11 worker missing use_quality_filters + RSI bounds + wrong import path

THREE critical bugs in cluster/v11_test_worker.py:

1. Missing use_quality_filters parameter when creating MoneyLineV11Inputs
   - Parameter defaults to True but wasn't being passed explicitly
   - Fix: Added use_quality_filters=True to inputs creation

2. Missing fixed RSI parameters (rsi_long_max, rsi_short_min)
   - Worker only passed rsi_long_min and rsi_short_max (sweep params)
   - Missing rsi_long_max=70 and rsi_short_min=30 (fixed params)
   - Fix: Added both fixed parameters to inputs creation

3. Import path mismatch - worker imported OLD version
   - Worker added cluster/ to sys.path, imported from parent directory
   - Old v11_moneyline_all_filters.py (21:40) missing use_quality_filters
   - Fixed v11_moneyline_all_filters.py was in backtester/ subdirectory
   - Fix: Deployed corrected file to /home/comprehensive_sweep/

Result: 0 signals → 1,096-1,186 signals per config ✓

Verified: Local test (314 signals), EPYC dataset test (1,186 signals),
Worker log now shows signal variety across 27 concurrent configs.

Progressive sweep now running successfully on EPYC cluster.
This commit is contained in:
mindesbunister
2025-12-06 22:52:35 +01:00
parent c7f2df09b9
commit 4291f31e64
6 changed files with 155 additions and 3 deletions

View File

@@ -0,0 +1,78 @@
import { NextRequest, NextResponse } from 'next/server'
import { initializeDriftService, getDriftService } from '@/lib/drift/client'
/**
* GET /api/drift/markets
*
* Query Drift Protocol perpetual markets
* Optional query param: ?search=FARTCOIN to filter by symbol
*/
export async function GET(request: NextRequest) {
try {
const searchParams = request.nextUrl.searchParams
const searchSymbol = searchParams.get('search')?.toUpperCase()
await initializeDriftService()
const driftService = getDriftService()
const driftClient = driftService.getClient()
const perpMarketAccounts = driftClient.getPerpMarketAccounts()
if (!perpMarketAccounts || perpMarketAccounts.length === 0) {
return NextResponse.json({ markets: [] })
}
const markets = perpMarketAccounts.map((market, index) => {
if (!market) return null
// Decode market name from bytes
const nameBytes = market.name as unknown as number[]
const symbol = nameBytes
? String.fromCharCode(...Array.from(nameBytes).filter((b: number) => b !== 0)).trim()
: `Market-${index}`
const minOrderSize = market.amm?.minOrderSize
? Number(market.amm.minOrderSize) / 1e9
: 0
const tickSize = market.amm?.orderTickSize
? Number(market.amm.orderTickSize) / 1e6
: 0.0001
const oracleAddress = market.amm?.oracle?.toString() || 'N/A'
return {
index,
symbol,
oracleAddress,
minOrderSize,
tickSize,
marginRatioInitial: market.marginRatioInitial
? Number(market.marginRatioInitial) / 10000
: 0,
marginRatioMaintenance: market.marginRatioMaintenance
? Number(market.marginRatioMaintenance) / 10000
: 0,
}
}).filter(Boolean)
// Filter by search if provided
const filtered = searchSymbol
? markets.filter(m => m && m.symbol.toUpperCase().includes(searchSymbol))
: markets
await driftService.disconnect()
return NextResponse.json({
total: markets.length,
filtered: filtered.length,
markets: filtered,
})
} catch (error: any) {
console.error('❌ Error fetching markets:', error)
return NextResponse.json(
{ error: 'Failed to fetch markets', message: error.message },
{ status: 500 }
)
}
}

Binary file not shown.

View File

@@ -215,7 +215,7 @@ def deploy_worker(worker_name: str, chunk_id: str, start_combo: int):
'scp', 'scp',
'-o', 'StrictHostKeyChecking=no', '-o', 'StrictHostKeyChecking=no',
'-o', f'ProxyJump={worker["ssh_hop"]}', '-o', f'ProxyJump={worker["ssh_hop"]}',
'cluster/v11_test_worker.py', 'v11_test_worker.py',
f'{worker["host"]}:{workspace}/' f'{worker["host"]}:{workspace}/'
] ]
else: else:
@@ -223,7 +223,7 @@ def deploy_worker(worker_name: str, chunk_id: str, start_combo: int):
scp_cmd = [ scp_cmd = [
'scp', 'scp',
'-o', 'StrictHostKeyChecking=no', '-o', 'StrictHostKeyChecking=no',
'cluster/v11_test_worker.py', 'v11_test_worker.py',
f'{worker["host"]}:{workspace}/' f'{worker["host"]}:{workspace}/'
] ]
@@ -263,7 +263,7 @@ def deploy_worker(worker_name: str, chunk_id: str, start_combo: int):
# Start worker # Start worker
print(f"🚀 Starting worker process...") print(f"🚀 Starting worker process...")
worker_cmd = f"cd {workspace} && nohup python3 v11_test_worker.py {DATA_FILE} {chunk_id} {start_combo} > {chunk_id}_worker.log 2>&1 &" worker_cmd = f"cd {workspace} && nohup .venv/bin/python3 v11_test_worker.py {DATA_FILE} {chunk_id} {start_combo} > {chunk_id}_worker.log 2>&1 &"
if 'ssh_hop' in worker: if 'ssh_hop' in worker:
ssh_cmd = [ ssh_cmd = [

View File

@@ -113,6 +113,7 @@ def backtest_config(config: Dict[str, Any]) -> Dict[str, Any]:
try: try:
# Create v11 inputs # Create v11 inputs
inputs = MoneyLineV11Inputs( inputs = MoneyLineV11Inputs(
use_quality_filters=True, # 🔧 FIX: Enable filters for progressive sweep
flip_threshold=config['flip_threshold'], flip_threshold=config['flip_threshold'],
adx_min=config['adx_min'], adx_min=config['adx_min'],
long_pos_max=config['long_pos_max'], long_pos_max=config['long_pos_max'],
@@ -120,6 +121,8 @@ def backtest_config(config: Dict[str, Any]) -> Dict[str, Any]:
vol_min=config['vol_min'], vol_min=config['vol_min'],
entry_buffer_atr=config['entry_buffer_atr'], entry_buffer_atr=config['entry_buffer_atr'],
rsi_long_min=config['rsi_long_min'], rsi_long_min=config['rsi_long_min'],
rsi_long_max=70, # 🔧 FIX: Add missing fixed parameter
rsi_short_min=30, # 🔧 FIX: Add missing fixed parameter
rsi_short_max=config['rsi_short_max'], rsi_short_max=config['rsi_short_max'],
) )

71
test_worker_params.py Normal file
View File

@@ -0,0 +1,71 @@
#!/usr/bin/env python3
"""Test exact parameters worker is using"""
import pandas as pd
import sys
sys.path.insert(0, 'backtester')
from v11_moneyline_all_filters import money_line_v11_signals, MoneyLineV11Inputs
# Load dataset
print("Loading data...")
df = pd.read_csv('data/solusdt_5m.csv')
df['timestamp'] = pd.to_datetime(df['timestamp'])
df = df.set_index('timestamp')
print(f"✓ Loaded {len(df)} bars")
# Test EXACT worker configuration (most permissive combination)
config = {
'flip_threshold': 0.4, # Most permissive
'adx_min': 0, # Filter DISABLED
'long_pos_max': 100, # Most permissive
'short_pos_min': 0, # Filter DISABLED
'vol_min': 0.0, # Filter DISABLED
'entry_buffer_atr': 0.0, # Filter DISABLED
'rsi_long_min': 25, # Permissive
'rsi_short_max': 80, # Permissive
}
print("\nTest 1: Worker parameters WITH use_quality_filters=True")
print(f"Config: {config}")
inputs = MoneyLineV11Inputs(
use_quality_filters=True,
flip_threshold=config['flip_threshold'],
adx_min=config['adx_min'],
long_pos_max=config['long_pos_max'],
short_pos_min=config['short_pos_min'],
vol_min=config['vol_min'],
entry_buffer_atr=config['entry_buffer_atr'],
rsi_long_min=config['rsi_long_min'],
rsi_long_max=70,
rsi_short_min=30,
rsi_short_max=config['rsi_short_max'],
)
print(f"use_quality_filters: {inputs.use_quality_filters}")
print(f"RSI bounds: long [{inputs.rsi_long_min}, {inputs.rsi_long_max}], short [{inputs.rsi_short_min}, {inputs.rsi_short_max}]")
signals = money_line_v11_signals(df, inputs)
print(f"RESULT: {len(signals)} signals")
if len(signals) == 0:
print("\n🔴 ZERO SIGNALS - Same as worker!")
print("\nTest 2: Try WITHOUT quality filters")
inputs2 = MoneyLineV11Inputs(
use_quality_filters=False, # Bypass all filters
flip_threshold=0.4,
)
signals2 = money_line_v11_signals(df, inputs2)
print(f"RESULT: {len(signals2)} signals")
if len(signals2) > 0:
print("\n✓ Filter bypass works - problem is WITH filters")
print("Debugging which filter is blocking...")
# Check each filter component
print("\n First 10 rows of data:")
print(df[['open', 'high', 'low', 'close', 'volume']].head(10))
else:
print(f"\n✅ SUCCESS: {len(signals)} signals generated!")
print(f" First 3 signals:")
for s in signals[:3]:
print(f" {s.timestamp} {s.direction} @ ${s.entry_price:.2f}")