Spaces:
Running
Running
Deploy Aureon OS (deploy/selfhost stack: nginx edge + fusion API x2 + console + HNC organ + redis + postgres; paper mode) (part 19)
da0ce7b verified Download scripts/traders/aggressiveWaveRider.ts from GaryLeckey/aureon-os: direct link, hf CLI and curl.
- Browser
- Download file 32.5 kB
-
https://huggingface.co/spaces/GaryLeckey/aureon-os/resolve/main/scripts/traders/aggressiveWaveRider.ts
- Command line
-
hf download hf://spaces/GaryLeckey/aureon-os/scripts/traders/aggressiveWaveRider.ts
-
curl -L -o aggressiveWaveRider.ts https://huggingface.co/spaces/GaryLeckey/aureon-os/resolve/main/scripts/traders/aggressiveWaveRider.ts
32.5 kB
| /** | |
| * π AGGRESSIVE WAVE RIDER - LIVE MARKETS π | |
| * | |
| * AβZ β ZβA "They Can't Stop Them All!" | |
| * | |
| * βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| * β THE WAVE RIDER STRATEGY - REAL PRICES, REAL TRADES β | |
| * β β | |
| * β β’ Scan AβZ on odd cycles, ZβA on even cycles β | |
| * β β’ Enter on momentum + trend alignment β | |
| * β β’ Ride the wave until stop loss or take profit β | |
| * β β’ Survive = preserve capital with tight risk management β | |
| * β β | |
| * βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| * | |
| * Author: Gary Leckey - R&A Consulting | |
| */ | |
| import * as dotenv from 'dotenv'; | |
| import * as path from 'path'; | |
| import { fileURLToPath } from 'url'; | |
| const __filename = fileURLToPath(import.meta.url); | |
| const __dirname = path.dirname(__filename); | |
| dotenv.config({ path: path.join(__dirname, '..', '.env') }); | |
| // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| // Configuration - AGGRESSIVE MODE | |
| // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| const CONFIG = { | |
| BALANCE_PER_BROKER: 20, | |
| // Lower threshold for more entries with live data | |
| ENTRY_THRESHOLD: 0.60, // Much lower - enter on any momentum | |
| MIN_HISTORY: 3, // Only need 3 ticks to start trading | |
| // Position sizing | |
| POSITION_SIZE_PCT: 0.15, // 15% per trade = Β£3 per position | |
| STOP_LOSS_PCT: 0.015, // 1.5% stop loss (tighter) | |
| TAKE_PROFIT_PCT: 0.03, // 3% take profit | |
| // Max positions per broker | |
| MAX_POSITIONS_PER_BROKER: 5, | |
| // Faster scanning | |
| SCAN_INTERVAL_MS: 5000, // 5 seconds | |
| }; | |
| // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| // Types | |
| // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| interface LivePrice { | |
| symbol: string; | |
| bid: number; | |
| ask: number; | |
| mid: number; | |
| spread: number; | |
| change24h?: number; | |
| } | |
| interface Position { | |
| broker: string; | |
| symbol: string; | |
| direction: 'LONG' | 'SHORT'; | |
| size: number; | |
| entryPrice: number; | |
| currentPrice: number; | |
| pnl: number; | |
| pnlPercent: number; | |
| taxFree: boolean; | |
| } | |
| interface BrokerState { | |
| name: string; | |
| emoji: string; | |
| balance: number; | |
| positions: number; | |
| wins: number; | |
| losses: number; | |
| pnl: number; | |
| taxFree: boolean; | |
| } | |
| // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| // Real Price Feeds | |
| // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| // BINANCE | |
| async function fetchBinancePrices(): Promise<LivePrice[]> { | |
| const symbols = [ | |
| 'BTCUSDT', 'ETHUSDT', 'BNBUSDT', 'SOLUSDT', 'XRPUSDT', | |
| 'DOGEUSDT', 'ADAUSDT', 'AVAXUSDT', 'DOTUSDT', 'LINKUSDT', | |
| 'MATICUSDT', 'LTCUSDT', 'NEARUSDT', 'UNIUSDT', 'AAVEUSDT', | |
| 'APTUSDT', 'ARBUSDT', 'OPUSDT', 'ATOMUSDT', 'SHIBUSDT' | |
| ]; | |
| try { | |
| const response = await fetch('https://api.binance.com/api/v3/ticker/24hr'); | |
| if (!response.ok) return []; | |
| const data = await response.json(); | |
| const prices: LivePrice[] = []; | |
| for (const sym of symbols) { | |
| const ticker = data.find((t: any) => t.symbol === sym); | |
| if (ticker) { | |
| const bid = parseFloat(ticker.bidPrice); | |
| const ask = parseFloat(ticker.askPrice); | |
| prices.push({ | |
| symbol: sym, | |
| bid, | |
| ask, | |
| mid: (bid + ask) / 2, | |
| spread: ask - bid, | |
| change24h: parseFloat(ticker.priceChangePercent) | |
| }); | |
| } | |
| } | |
| return prices; | |
| } catch { return []; } | |
| } | |
| // KRAKEN | |
| async function fetchKrakenPrices(): Promise<LivePrice[]> { | |
| const pairs = 'XXBTZGBP,XETHZGBP,XXBTZUSD,XETHZUSD,SOLUSD,XRPUSD,ADAUSD,DOTUSD,LINKUSD,ATOMUSD'; | |
| try { | |
| const response = await fetch(`https://api.kraken.com/0/public/Ticker?pair=${pairs}`); | |
| if (!response.ok) return []; | |
| const data = await response.json(); | |
| if (data.error?.length > 0) return []; | |
| const prices: LivePrice[] = []; | |
| for (const [key, ticker] of Object.entries(data.result) as any) { | |
| const bid = parseFloat(ticker.b[0]); | |
| const ask = parseFloat(ticker.a[0]); | |
| const open = parseFloat(ticker.o); | |
| const last = parseFloat(ticker.c[0]); | |
| prices.push({ | |
| symbol: key, | |
| bid, | |
| ask, | |
| mid: (bid + ask) / 2, | |
| spread: ask - bid, | |
| change24h: ((last - open) / open) * 100 | |
| }); | |
| } | |
| return prices; | |
| } catch { return []; } | |
| } | |
| // OKX | |
| async function fetchOKXPrices(): Promise<LivePrice[]> { | |
| const symbols = [ | |
| 'BTC-USDT', 'ETH-USDT', 'SOL-USDT', 'XRP-USDT', 'DOGE-USDT', | |
| 'ADA-USDT', 'DOT-USDT', 'AVAX-USDT', 'LINK-USDT', 'NEAR-USDT', | |
| 'ATOM-USDT', 'UNI-USDT', 'AAVE-USDT', 'LTC-USDT', 'ARB-USDT' | |
| ]; | |
| try { | |
| const response = await fetch('https://www.okx.com/api/v5/market/tickers?instType=SPOT'); | |
| if (!response.ok) return []; | |
| const data = await response.json(); | |
| if (!data.data) return []; | |
| const prices: LivePrice[] = []; | |
| for (const sym of symbols) { | |
| const ticker = data.data.find((t: any) => t.instId === sym); | |
| if (ticker) { | |
| const bid = parseFloat(ticker.bidPx); | |
| const ask = parseFloat(ticker.askPx); | |
| const open = parseFloat(ticker.open24h); | |
| const last = parseFloat(ticker.last); | |
| prices.push({ | |
| symbol: sym, | |
| bid, | |
| ask, | |
| mid: (bid + ask) / 2, | |
| spread: ask - bid, | |
| change24h: ((last - open) / open) * 100 | |
| }); | |
| } | |
| } | |
| return prices; | |
| } catch { return []; } | |
| } | |
| // COINBASE | |
| async function fetchCoinbasePrices(): Promise<LivePrice[]> { | |
| const symbols = ['BTC-GBP', 'ETH-GBP', 'SOL-GBP', 'BTC-USD', 'ETH-USD', 'SOL-USD', 'DOGE-USD', 'ADA-USD']; | |
| const prices: LivePrice[] = []; | |
| for (const sym of symbols) { | |
| try { | |
| const response = await fetch(`https://api.exchange.coinbase.com/products/${sym}/ticker`); | |
| if (response.ok) { | |
| const data = await response.json(); | |
| const bid = parseFloat(data.bid); | |
| const ask = parseFloat(data.ask); | |
| prices.push({ | |
| symbol: sym, | |
| bid, | |
| ask, | |
| mid: (bid + ask) / 2, | |
| spread: ask - bid | |
| }); | |
| } | |
| } catch {} | |
| } | |
| return prices; | |
| } | |
| // BITSTAMP | |
| async function fetchBitstampPrices(): Promise<LivePrice[]> { | |
| const symbols = ['btcgbp', 'ethgbp', 'btcusd', 'ethusd', 'xrpusd', 'ltcusd', 'solusd']; | |
| const prices: LivePrice[] = []; | |
| for (const sym of symbols) { | |
| try { | |
| const response = await fetch(`https://www.bitstamp.net/api/v2/ticker/${sym}/`); | |
| if (response.ok) { | |
| const data = await response.json(); | |
| const bid = parseFloat(data.bid); | |
| const ask = parseFloat(data.ask); | |
| const open = parseFloat(data.open); | |
| const last = parseFloat(data.last); | |
| prices.push({ | |
| symbol: sym.toUpperCase(), | |
| bid, | |
| ask, | |
| mid: (bid + ask) / 2, | |
| spread: ask - bid, | |
| change24h: ((last - open) / open) * 100 | |
| }); | |
| } | |
| } catch {} | |
| } | |
| return prices; | |
| } | |
| // FOREX (Free API) | |
| async function fetchForexPrices(): Promise<LivePrice[]> { | |
| try { | |
| const response = await fetch('https://api.exchangerate-api.com/v4/latest/USD'); | |
| if (!response.ok) return []; | |
| const data = await response.json(); | |
| const prices: LivePrice[] = []; | |
| // Major pairs | |
| const pairs = [ | |
| { base: 'EUR', symbol: 'EUR/USD' }, | |
| { base: 'GBP', symbol: 'GBP/USD' }, | |
| { base: 'JPY', symbol: 'USD/JPY' }, | |
| { base: 'CHF', symbol: 'USD/CHF' }, | |
| { base: 'AUD', symbol: 'AUD/USD' }, | |
| { base: 'CAD', symbol: 'USD/CAD' }, | |
| ]; | |
| for (const pair of pairs) { | |
| const rate = data.rates[pair.base]; | |
| if (rate) { | |
| let mid: number; | |
| if (pair.symbol.startsWith('USD/')) { | |
| mid = rate; | |
| } else { | |
| mid = 1 / rate; | |
| } | |
| const spread = mid * 0.0002; | |
| prices.push({ | |
| symbol: pair.symbol, | |
| bid: mid - spread / 2, | |
| ask: mid + spread / 2, | |
| mid, | |
| spread | |
| }); | |
| } | |
| } | |
| return prices; | |
| } catch { return []; } | |
| } | |
| // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| // Wave Rider Engine | |
| // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| class WaveRiderEngine { | |
| private priceHistory: Map<string, number[]> = new Map(); | |
| private PHI = 1.618033988749895; | |
| addPrice(key: string, price: number): void { | |
| if (!this.priceHistory.has(key)) { | |
| this.priceHistory.set(key, []); | |
| } | |
| const history = this.priceHistory.get(key)!; | |
| history.push(price); | |
| if (history.length > 50) history.shift(); | |
| } | |
| getHistoryLength(key: string): number { | |
| return this.priceHistory.get(key)?.length || 0; | |
| } | |
| // Wave analysis - detect momentum and trend | |
| analyzeWave(key: string): { signal: 'BUY' | 'SELL' | 'HOLD'; strength: number; trend: string } { | |
| const history = this.priceHistory.get(key); | |
| if (!history || history.length < CONFIG.MIN_HISTORY) { | |
| return { signal: 'HOLD', strength: 0, trend: 'building' }; | |
| } | |
| const recent = history.slice(-10); | |
| const current = recent[recent.length - 1]; | |
| const previous = recent[recent.length - 2] || current; | |
| const oldest = recent[0]; | |
| // Immediate momentum (last tick) | |
| const tickMomentum = (current - previous) / previous; | |
| // Short-term trend (last few ticks) | |
| const shortTrend = (current - oldest) / oldest; | |
| // Volatility check | |
| const min = Math.min(...recent); | |
| const max = Math.max(...recent); | |
| const range = max - min; | |
| const volatility = range / ((max + min) / 2); | |
| // Wave position (PHI levels) | |
| const normalized = range > 0 ? (current - min) / range : 0.5; | |
| const phiLevel = 1 / this.PHI; // 0.618 | |
| const atPhiSupport = normalized < 0.4; // Near bottom | |
| const atPhiResistance = normalized > 0.7; // Near top | |
| // Signal logic based on wave position and momentum | |
| let signal: 'BUY' | 'SELL' | 'HOLD' = 'HOLD'; | |
| let strength = 0; | |
| let trend = 'neutral'; | |
| // BUY: At support with upward momentum | |
| if (atPhiSupport && tickMomentum > 0 && shortTrend > -0.01) { | |
| signal = 'BUY'; | |
| strength = Math.min(1, Math.abs(tickMomentum) * 100 + 0.5); | |
| trend = 'reversal-up'; | |
| } | |
| // BUY: Strong uptrend continuation | |
| else if (shortTrend > 0.002 && tickMomentum > 0) { | |
| signal = 'BUY'; | |
| strength = Math.min(1, shortTrend * 50 + 0.3); | |
| trend = 'uptrend'; | |
| } | |
| // SELL: At resistance with downward momentum | |
| else if (atPhiResistance && tickMomentum < 0 && shortTrend < 0.01) { | |
| signal = 'SELL'; | |
| strength = Math.min(1, Math.abs(tickMomentum) * 100 + 0.5); | |
| trend = 'reversal-down'; | |
| } | |
| // SELL: Strong downtrend continuation | |
| else if (shortTrend < -0.002 && tickMomentum < 0) { | |
| signal = 'SELL'; | |
| strength = Math.min(1, Math.abs(shortTrend) * 50 + 0.3); | |
| trend = 'downtrend'; | |
| } | |
| // Volatility boost | |
| if (volatility > 0.005 && signal !== 'HOLD') { | |
| strength = Math.min(1, strength + 0.2); | |
| } | |
| return { signal, strength, trend }; | |
| } | |
| } | |
| // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| // Aggressive Wave Rider | |
| // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| class AggressiveWaveRider { | |
| private engine = new WaveRiderEngine(); | |
| private positions: Map<string, Position> = new Map(); | |
| private brokers: Map<string, BrokerState> = new Map(); | |
| private scanDirection: 'AβZ' | 'ZβA' = 'AβZ'; | |
| private scans = 0; | |
| private startTime = new Date(); | |
| private totalPnL = 0; | |
| private wins = 0; | |
| private losses = 0; | |
| constructor() { | |
| this.initBrokers(); | |
| } | |
| private initBrokers() { | |
| const brokerList = [ | |
| { name: 'Binance', emoji: 'πͺ', taxFree: false }, | |
| { name: 'Kraken', emoji: 'π¦', taxFree: false }, | |
| { name: 'Coinbase', emoji: 'π ', taxFree: false }, | |
| { name: 'Bitstamp', emoji: 'π', taxFree: false }, | |
| { name: 'OKX', emoji: 'β', taxFree: false }, | |
| { name: 'OANDA', emoji: 'π±', taxFree: false }, | |
| { name: 'FXCM', emoji: 'πΉ', taxFree: false }, | |
| { name: 'IG', emoji: 'π', taxFree: true }, | |
| { name: 'CMC', emoji: 'π', taxFree: true }, | |
| { name: 'Capital', emoji: 'π', taxFree: false }, | |
| { name: 'Saxo', emoji: 'π¦', taxFree: false }, | |
| { name: 'IB', emoji: 'ποΈ', taxFree: false }, | |
| { name: 'Alpaca', emoji: 'π¦', taxFree: false }, | |
| { name: 'Gemini', emoji: 'π ', taxFree: false }, | |
| ]; | |
| for (const b of brokerList) { | |
| this.brokers.set(b.name, { | |
| name: b.name, | |
| emoji: b.emoji, | |
| balance: CONFIG.BALANCE_PER_BROKER, | |
| positions: 0, | |
| wins: 0, | |
| losses: 0, | |
| pnl: 0, | |
| taxFree: b.taxFree | |
| }); | |
| } | |
| } | |
| async start(): Promise<void> { | |
| this.printHeader(); | |
| console.log('\n π‘ Connecting to live markets...\n'); | |
| while (true) { | |
| this.scans++; | |
| this.scanDirection = this.scanDirection === 'AβZ' ? 'ZβA' : 'AβZ'; | |
| await this.executeScan(); | |
| this.displayStatus(); | |
| await new Promise(r => setTimeout(r, CONFIG.SCAN_INTERVAL_MS)); | |
| } | |
| } | |
| private async executeScan(): Promise<void> { | |
| // Fetch all prices in parallel | |
| const [binance, kraken, okx, coinbase, bitstamp, forex] = await Promise.all([ | |
| fetchBinancePrices(), | |
| fetchKrakenPrices(), | |
| fetchOKXPrices(), | |
| fetchCoinbasePrices(), | |
| fetchBitstampPrices(), | |
| fetchForexPrices() | |
| ]); | |
| // Sort by direction | |
| const sortFn = (a: LivePrice, b: LivePrice) => { | |
| const cmp = a.symbol.localeCompare(b.symbol); | |
| return this.scanDirection === 'AβZ' ? cmp : -cmp; | |
| }; | |
| // Process each exchange | |
| this.processPrices('Binance', binance.sort(sortFn)); | |
| this.processPrices('Kraken', kraken.sort(sortFn)); | |
| this.processPrices('OKX', okx.sort(sortFn)); | |
| this.processPrices('Coinbase', coinbase.sort(sortFn)); | |
| this.processPrices('Bitstamp', bitstamp.sort(sortFn)); | |
| // Forex goes to multiple brokers | |
| const sortedForex = forex.sort(sortFn); | |
| this.processPrices('OANDA', sortedForex); | |
| this.processPrices('FXCM', sortedForex); | |
| this.processPrices('IG', sortedForex); | |
| this.processPrices('CMC', sortedForex); | |
| this.processPrices('Saxo', sortedForex); | |
| } | |
| private processPrices(broker: string, prices: LivePrice[]): void { | |
| const brokerState = this.brokers.get(broker); | |
| if (!brokerState) return; | |
| for (const price of prices) { | |
| const key = `${broker}:${price.symbol}`; | |
| // Add to history | |
| this.engine.addPrice(key, price.mid); | |
| // Check existing position | |
| const existingPos = this.positions.get(key); | |
| if (existingPos) { | |
| this.updatePosition(key, price.mid); | |
| continue; | |
| } | |
| // Check if we can open new position | |
| if (brokerState.positions >= CONFIG.MAX_POSITIONS_PER_BROKER) continue; | |
| // Analyze wave | |
| const analysis = this.engine.analyzeWave(key); | |
| // Enter on signal with sufficient strength | |
| if (analysis.signal !== 'HOLD' && analysis.strength >= CONFIG.ENTRY_THRESHOLD) { | |
| this.openPosition(broker, price, analysis.signal, analysis.strength, analysis.trend); | |
| } | |
| } | |
| } | |
| private openPosition(broker: string, price: LivePrice, signal: 'BUY' | 'SELL', strength: number, trend: string): void { | |
| const brokerState = this.brokers.get(broker); | |
| if (!brokerState) return; | |
| const key = `${broker}:${price.symbol}`; | |
| const direction = signal === 'BUY' ? 'LONG' : 'SHORT'; | |
| const entryPrice = signal === 'BUY' ? price.ask : price.bid; | |
| const size = (brokerState.balance * CONFIG.POSITION_SIZE_PCT) / entryPrice; | |
| this.positions.set(key, { | |
| broker, | |
| symbol: price.symbol, | |
| direction, | |
| size, | |
| entryPrice, | |
| currentPrice: price.mid, | |
| pnl: 0, | |
| pnlPercent: 0, | |
| taxFree: brokerState.taxFree | |
| }); | |
| brokerState.positions++; | |
| const dir = this.scanDirection; | |
| const taxLabel = brokerState.taxFree ? ' π' : ''; | |
| const priceStr = price.mid < 10 ? price.mid.toFixed(5) : price.mid.toFixed(2); | |
| console.log(` ${brokerState.emoji} [${dir}] β‘ ${signal}: ${price.symbol} @ ${priceStr} (${trend}, ${(strength*100).toFixed(0)}%)${taxLabel}`); | |
| } | |
| private updatePosition(key: string, currentPrice: number): void { | |
| const pos = this.positions.get(key); | |
| if (!pos) return; | |
| const brokerState = this.brokers.get(pos.broker); | |
| if (!brokerState) return; | |
| pos.currentPrice = currentPrice; | |
| const priceDiff = currentPrice - pos.entryPrice; | |
| const multiplier = pos.direction === 'LONG' ? 1 : -1; | |
| pos.pnl = priceDiff * pos.size * multiplier; | |
| pos.pnlPercent = (priceDiff / pos.entryPrice) * 100 * multiplier; | |
| // Check stop loss | |
| if (pos.pnlPercent <= -CONFIG.STOP_LOSS_PCT * 100) { | |
| this.closePosition(key, 'STOP'); | |
| } | |
| // Check take profit | |
| else if (pos.pnlPercent >= CONFIG.TAKE_PROFIT_PCT * 100) { | |
| this.closePosition(key, 'PROFIT'); | |
| } | |
| } | |
| private closePosition(key: string, reason: 'STOP' | 'PROFIT'): void { | |
| const pos = this.positions.get(key); | |
| if (!pos) return; | |
| const brokerState = this.brokers.get(pos.broker); | |
| if (!brokerState) return; | |
| brokerState.balance += pos.pnl; | |
| brokerState.pnl += pos.pnl; | |
| this.totalPnL += pos.pnl; | |
| if (pos.pnl >= 0) { | |
| brokerState.wins++; | |
| this.wins++; | |
| } else { | |
| brokerState.losses++; | |
| this.losses++; | |
| } | |
| brokerState.positions--; | |
| const emoji = pos.pnl >= 0 ? 'β ' : 'β'; | |
| const taxLabel = pos.taxFree ? ' πTAX FREE!' : ''; | |
| const pnlStr = pos.pnl >= 0 ? `+Β£${pos.pnl.toFixed(4)}` : `-Β£${Math.abs(pos.pnl).toFixed(4)}`; | |
| console.log(` ${brokerState.emoji} ${emoji} ${reason}: ${pos.symbol} | P&L: ${pnlStr}${taxLabel}`); | |
| this.positions.delete(key); | |
| } | |
| private printHeader(): void { | |
| console.log('\n'); | |
| console.log(' βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ'); | |
| console.log(' β β'); | |
| console.log(' β π AGGRESSIVE WAVE RIDER - LIVE MARKETS π β'); | |
| console.log(' β β'); | |
| console.log(' β AβZ β ZβA "They Can\'t Stop Them All!" β'); | |
| console.log(' β β'); | |
| console.log(' β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£'); | |
| console.log(' β β'); | |
| console.log(' β CRYPTO: πͺ Binance π¦ Kraken π Coinbase π Bitstamp π Gemini β OKX β'); | |
| console.log(' β FOREX: π± OANDA πΉ FXCM π¦ Saxo ποΈ IB β'); | |
| console.log(' β CFD: π Capital π IG π CMC π¦ Alpaca β'); | |
| console.log(' β β'); | |
| console.log(' β π TAX FREE (Spread Betting): π IG π CMC β'); | |
| console.log(' β β'); | |
| console.log(' β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£'); | |
| console.log(` β Capital: Β£${CONFIG.BALANCE_PER_BROKER} Γ 14 = Β£${CONFIG.BALANCE_PER_BROKER * 14} | Entry: ${CONFIG.ENTRY_THRESHOLD*100}% | SL: ${CONFIG.STOP_LOSS_PCT*100}% | TP: ${CONFIG.TAKE_PROFIT_PCT*100}% β`); | |
| console.log(' βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ'); | |
| console.log(''); | |
| console.log(' π Wave Rider activated - riding AβZ β ZβA on live markets...'); | |
| console.log(' ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ'); | |
| } | |
| private displayStatus(): void { | |
| const elapsed = Math.floor((Date.now() - this.startTime.getTime()) / 1000); | |
| const minutes = Math.floor(elapsed / 60); | |
| const seconds = elapsed % 60; | |
| let totalBalance = 0; | |
| let totalPositions = 0; | |
| let taxFreePnL = 0; | |
| const lines: string[] = []; | |
| for (const [name, state] of this.brokers) { | |
| totalBalance += state.balance; | |
| totalPositions += state.positions; | |
| if (state.taxFree) taxFreePnL += state.pnl; | |
| const hitRate = state.wins + state.losses > 0 | |
| ? ((state.wins / (state.wins + state.losses)) * 100).toFixed(0) | |
| : '-'; | |
| const pnlStr = state.pnl >= 0 ? `+Β£${state.pnl.toFixed(2)}` : `-Β£${Math.abs(state.pnl).toFixed(2)}`; | |
| const pnlEmoji = state.pnl >= 0 ? 'π’' : 'π΄'; | |
| const taxLabel = state.taxFree ? 'π' : ' '; | |
| lines.push( | |
| ` β ${state.emoji} ${state.name.padEnd(8)} β Β£${state.balance.toFixed(2).padStart(6)} β ${state.positions}/${CONFIG.MAX_POSITIONS_PER_BROKER} β ${hitRate.padStart(3)}% β ${pnlEmoji} ${pnlStr.padStart(8)} β ${taxLabel} β` | |
| ); | |
| } | |
| const totalHitRate = this.wins + this.losses > 0 | |
| ? ((this.wins / (this.wins + this.losses)) * 100).toFixed(1) | |
| : '0.0'; | |
| const totalPnLStr = this.totalPnL >= 0 ? `+Β£${this.totalPnL.toFixed(2)}` : `-Β£${Math.abs(this.totalPnL).toFixed(2)}`; | |
| const totalEmoji = this.totalPnL >= 0 ? 'π’' : 'π΄'; | |
| console.log(''); | |
| console.log(' ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ'); | |
| console.log(` β SCAN #${this.scans.toString().padStart(5)} [${this.scanDirection}] β Time: ${minutes}m ${seconds}s β Positions: ${totalPositions}/${14 * CONFIG.MAX_POSITIONS_PER_BROKER} β`); | |
| console.log(' ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€'); | |
| console.log(' β Broker β Balance β Pos β HR β P&L β π β'); | |
| console.log(' ββββββββββββββΌβββββββββββΌββββββΌβββββββΌβββββββββββββΌβββββ€'); | |
| for (const line of lines) { | |
| console.log(line); | |
| } | |
| console.log(' ββββββββββββββΌβββββββββββΌββββββΌβββββββΌβββββββββββββΌβββββ€'); | |
| console.log(` β π TOTAL β Β£${totalBalance.toFixed(2).padStart(6)} β ${totalPositions.toString().padStart(2)} β${totalHitRate.padStart(5)}% β ${totalEmoji} ${totalPnLStr.padStart(8)} β β`); | |
| console.log(' ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ'); | |
| if (taxFreePnL !== 0) { | |
| const taxFreeStr = taxFreePnL >= 0 ? `+Β£${taxFreePnL.toFixed(4)}` : `-Β£${Math.abs(taxFreePnL).toFixed(4)}`; | |
| console.log(` π Tax-Free P&L (IG + CMC): ${taxFreeStr}`); | |
| } | |
| this.displayPositions(); | |
| } | |
| private displayPositions(): void { | |
| const allPositions = Array.from(this.positions.values()); | |
| if (allPositions.length === 0) { | |
| console.log(''); | |
| console.log(` π [${this.scanDirection}] Scanning markets for wave entry points...`); | |
| console.log(''); | |
| return; | |
| } | |
| allPositions.sort((a, b) => b.pnl - a.pnl); | |
| console.log(''); | |
| console.log(` π Active Positions [${this.scanDirection}]:`); | |
| console.log(''); | |
| for (const pos of allPositions.slice(0, 12)) { | |
| const emoji = pos.pnl >= 0 ? 'π’' : 'π΄'; | |
| const dir = pos.direction === 'LONG' ? 'β¬' : 'β¬'; | |
| const brokerState = this.brokers.get(pos.broker); | |
| const brokerEmoji = brokerState?.emoji || 'π'; | |
| const taxLabel = pos.taxFree ? ' π' : ''; | |
| const pnlStr = pos.pnl >= 0 ? `+Β£${pos.pnl.toFixed(4)}` : `-Β£${Math.abs(pos.pnl).toFixed(4)}`; | |
| const priceStr = pos.currentPrice < 10 ? pos.currentPrice.toFixed(5) : pos.currentPrice.toFixed(2); | |
| console.log(` ${brokerEmoji} ${emoji} ${pos.symbol.padEnd(12)} ${dir} β ${pnlStr} (${pos.pnlPercent.toFixed(2)}%)${taxLabel}`); | |
| } | |
| if (allPositions.length > 12) { | |
| console.log(` ... and ${allPositions.length - 12} more positions`); | |
| } | |
| console.log(''); | |
| } | |
| } | |
| // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| // Main | |
| // βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| async function main() { | |
| console.log(` | |
| βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| β β | |
| β π WAVE RIDER - AGGRESSIVE LIVE TRADING π β | |
| β β | |
| β Strategy: β | |
| β β’ AβZ on odd scans, ZβA on even scans β | |
| β β’ Enter on momentum + PHI wave analysis β | |
| β β’ Ride the wave with 1.5% SL / 3% TP β | |
| β β’ "They can't stop them all!" β | |
| β β | |
| β Live Data Sources: β | |
| β β’ Binance API (20 pairs) β | |
| β β’ Kraken API (10 pairs) β | |
| β β’ OKX API (15 pairs) β | |
| β β’ Coinbase API (8 pairs) β | |
| β β’ Bitstamp API (7 pairs) β | |
| β β’ Forex API (6 major pairs) β | |
| β β | |
| β Author: Gary Leckey - R&A Consulting β | |
| β β | |
| βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| `); | |
| const rider = new AggressiveWaveRider(); | |
| process.on('SIGINT', () => { | |
| console.log('\n'); | |
| console.log(' ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ'); | |
| console.log(' π Wave Rider concludes...'); | |
| console.log(' ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ'); | |
| console.log(''); | |
| console.log(' "AβZ β ZβA - The wave rides eternal"'); | |
| console.log(''); | |
| process.exit(0); | |
| }); | |
| await rider.start(); | |
| } | |
| main().catch(console.error); | |