97 lines
4.1 KiB
TypeScript
97 lines
4.1 KiB
TypeScript
|
|
import { supabaseService } from '../src/services/SupabaseService.js';
|
|
import { AutoTrader } from '../src/services/AutoTrader.js';
|
|
import { TradeExecutor } from '../src/services/TradeExecutor.js';
|
|
import { AlpacaConnector } from '../src/connectors/alpaca.js';
|
|
import { ProStrategyEngine } from '../src/strategies/ProStrategyEngine.js';
|
|
import { config } from '../src/config/index.js';
|
|
import { SignalDirection, MarketContext } from '../src/strategies/rules/types.js';
|
|
import logger from '../src/utils/logger.js';
|
|
|
|
config.ENABLE_TRADING = true;
|
|
config.PAPER_TRADING = true;
|
|
|
|
const SLEEP_MS = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
|
|
|
|
async function runParamVerification() {
|
|
logger.info('===================================================');
|
|
logger.info('🧪 STARTING PARAMETER-AWARE E2E VERIFICATION');
|
|
logger.info(' Testing contrast between High Risk and Low Risk settings.');
|
|
logger.info('===================================================');
|
|
|
|
// 1. Fetch our two distinct profiles
|
|
const profiles = await supabaseService.getActiveProfiles();
|
|
const highRisk = profiles.find(p => p.name.includes('High Risk'));
|
|
const lowRisk = profiles.find(p => p.name.includes('Low Risk'));
|
|
|
|
if (!highRisk || !lowRisk) {
|
|
logger.error('❌ Could not find both profiles (Scalper and Swing). Run create scripts first.');
|
|
process.exit(1);
|
|
}
|
|
|
|
const user = highRisk.users; // Both belong to same user in our setup
|
|
const exchange = new AlpacaConnector(user.ALPACA_API_KEY, user.ALPACA_SECRET_KEY);
|
|
const engine = new ProStrategyEngine(exchange);
|
|
|
|
// 2. Setup Traders
|
|
const executorHigh = new TradeExecutor(exchange, undefined, user.user_id, highRisk.id);
|
|
const traderHigh = new AutoTrader(executorHigh, exchange, highRisk, engine);
|
|
|
|
const executorLow = new TradeExecutor(exchange, undefined, user.user_id, lowRisk.id);
|
|
const traderLow = new AutoTrader(executorLow, exchange, lowRisk, engine);
|
|
|
|
// 3. Define Market Context with RSI = 75
|
|
// Scenario: RSI is 75.
|
|
// Low Risk Swing logic (default RSI 70) -> Should Trigger SELL
|
|
// High Risk Scalper logic (custom RSI 80) -> Should NOT Trigger (75 < 80)
|
|
const mockCandles = Array(100).fill({ close: 65000, high: 65100, low: 64900, open: 65000, volume: 100 });
|
|
const mockContext: MarketContext = {
|
|
symbol: 'BTC/USD',
|
|
currentPrice: 65000,
|
|
candles1h: mockCandles,
|
|
candles15m: mockCandles,
|
|
candles4h: mockCandles,
|
|
rsi_1h: 75, // THE MAGIC NUMBER
|
|
ema20_1h: 64000,
|
|
ema50_4h: 60000,
|
|
ema200_4h: 55000,
|
|
session: 'NY', isMajorSession: true,
|
|
volatility: 'Med', change24h: 1, changeToday: 0.5,
|
|
latestSignal: SignalDirection.NONE
|
|
};
|
|
|
|
const analysis: any = {
|
|
symbol: 'BTC/USD',
|
|
globalSignal: SignalDirection.NONE,
|
|
rules: {}, // Global results don't matter now as we re-evaluate
|
|
context: mockContext
|
|
};
|
|
|
|
logger.info('\n📊 Scenario: RSI is 75');
|
|
logger.info(` Profile [Low Risk]: Threshold 70 -> Expected: PASS`);
|
|
logger.info(` Profile [High Risk]: Threshold 80 -> Expected: FAIL`);
|
|
|
|
// 4. Test Execution
|
|
logger.info('\n⚡ Testing [Low Risk Swing]...');
|
|
await traderLow.handleSignal('BTC/USD', analysis);
|
|
|
|
logger.info('⚡ Testing [High Risk Scalper]...');
|
|
await traderHigh.handleSignal('BTC/USD', analysis);
|
|
|
|
// 5. Verification
|
|
logger.info('\n🏁 RESULTS:');
|
|
// We can't easily wait for orders in this fake test without mocking exchange,
|
|
// but we can look at the logs to see where "EXECUTING" appeared.
|
|
|
|
logger.info('===================================================');
|
|
logger.info('✅ VERIFICATION COMPLETE');
|
|
logger.info(' Please check the logs above for "EXECUTING" vs "Blocked" messages.');
|
|
logger.info('===================================================');
|
|
process.exit(0);
|
|
}
|
|
|
|
runParamVerification().catch(err => {
|
|
logger.error('Test Failed:', err);
|
|
process.exit(1);
|
|
});
|