/** * Trading Bot Settings UI * * Beautiful interface for managing trading parameters */ 'use client' import { useState, useEffect } from 'react' interface TradingSettings { MAX_POSITION_SIZE_USD: number LEVERAGE: number STOP_LOSS_PERCENT: number TAKE_PROFIT_1_PERCENT: number TAKE_PROFIT_2_PERCENT: number EMERGENCY_STOP_PERCENT: number BREAKEVEN_TRIGGER_PERCENT: number PROFIT_LOCK_TRIGGER_PERCENT: number PROFIT_LOCK_PERCENT: number MAX_DAILY_DRAWDOWN: number MAX_TRADES_PER_HOUR: number MIN_TIME_BETWEEN_TRADES: number SLIPPAGE_TOLERANCE: number DRY_RUN: boolean } export default function SettingsPage() { const [settings, setSettings] = useState(null) const [loading, setLoading] = useState(true) const [saving, setSaving] = useState(false) const [restarting, setRestarting] = useState(false) const [message, setMessage] = useState<{ type: 'success' | 'error', text: string } | null>(null) useEffect(() => { loadSettings() }, []) const loadSettings = async () => { try { const response = await fetch('/api/settings') const data = await response.json() setSettings(data) setLoading(false) } catch (error) { setMessage({ type: 'error', text: 'Failed to load settings' }) setLoading(false) } } const saveSettings = async () => { setSaving(true) setMessage(null) try { const response = await fetch('/api/settings', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(settings), }) if (response.ok) { setMessage({ type: 'success', text: 'Settings saved! Click "Restart Bot" to apply changes.' }) } else { setMessage({ type: 'error', text: 'Failed to save settings' }) } } catch (error) { setMessage({ type: 'error', text: 'Failed to save settings' }) } setSaving(false) } const restartBot = async () => { setRestarting(true) setMessage(null) try { const response = await fetch('/api/restart', { method: 'POST', }) if (response.ok) { setMessage({ type: 'success', text: 'Bot is restarting... Settings will be applied in ~10 seconds.' }) } else { setMessage({ type: 'error', text: 'Failed to restart bot. Please restart manually with: docker restart trading-bot' }) } } catch (error) { setMessage({ type: 'error', text: 'Failed to restart bot. Please restart manually with: docker restart trading-bot' }) } setRestarting(false) } const updateSetting = (key: keyof TradingSettings, value: any) => { if (!settings) return setSettings({ ...settings, [key]: value }) } const calculateRisk = () => { if (!settings) return null const maxLoss = settings.MAX_POSITION_SIZE_USD * settings.LEVERAGE * (Math.abs(settings.STOP_LOSS_PERCENT) / 100) const tp1Gain = settings.MAX_POSITION_SIZE_USD * settings.LEVERAGE * (settings.TAKE_PROFIT_1_PERCENT / 100) const tp2Gain = settings.MAX_POSITION_SIZE_USD * settings.LEVERAGE * (settings.TAKE_PROFIT_2_PERCENT / 100) const fullWin = tp1Gain / 2 + tp2Gain / 2 // 50% at each TP return { maxLoss, tp1Gain, tp2Gain, fullWin } } if (loading) { return (
Loading settings...
) } if (!settings) return null const risk = calculateRisk() return (
{/* Header */}

โš™๏ธ Trading Bot Settings

Configure your automated trading parameters

{/* Message */} {message && (
{message.text}
)} {/* Risk Calculator */} {risk && (

๐Ÿ“Š Risk Calculator

Max Loss (SL)
-${risk.maxLoss.toFixed(2)}
TP1 Gain (50%)
+${(risk.tp1Gain / 2).toFixed(2)}
TP2 Gain (50%)
+${(risk.tp2Gain / 2).toFixed(2)}
Full Win
+${risk.fullWin.toFixed(2)}
Risk/Reward Ratio: 1:{(risk.fullWin / risk.maxLoss).toFixed(2)}
)} {/* Settings Sections */}
{/* Position Sizing */}
updateSetting('MAX_POSITION_SIZE_USD', v)} min={10} max={10000} step={10} description="Base USD amount per trade. With 5x leverage, $50 = $250 position." /> updateSetting('LEVERAGE', v)} min={1} max={20} step={1} description="Multiplier for your position. Higher = more profit AND more risk." />
{/* Risk Management */}
updateSetting('STOP_LOSS_PERCENT', v)} min={-10} max={-0.1} step={0.1} description="Close 100% of position when price drops this much. Protects from large losses." /> updateSetting('TAKE_PROFIT_1_PERCENT', v)} min={0.1} max={10} step={0.1} description="Close 50% of position at this profit level. Locks in early gains." /> updateSetting('TAKE_PROFIT_2_PERCENT', v)} min={0.1} max={20} step={0.1} description="Close remaining 50% at this profit level. Captures larger moves." /> updateSetting('EMERGENCY_STOP_PERCENT', v)} min={-20} max={-0.1} step={0.1} description="Hard stop for flash crashes. Should be wider than regular SL." />
{/* Dynamic Adjustments */}
updateSetting('BREAKEVEN_TRIGGER_PERCENT', v)} min={0} max={5} step={0.1} description="Move SL to breakeven (entry price) when profit reaches this level." /> updateSetting('PROFIT_LOCK_TRIGGER_PERCENT', v)} min={0} max={10} step={0.1} description="When profit reaches this level, lock in profit by moving SL." /> updateSetting('PROFIT_LOCK_PERCENT', v)} min={0} max={5} step={0.1} description="Move SL to this profit level when lock trigger is hit." />
{/* Trade Limits */}
updateSetting('MAX_DAILY_DRAWDOWN', v)} min={-1000} max={-10} step={10} description="Stop trading if daily loss exceeds this amount." /> updateSetting('MAX_TRADES_PER_HOUR', v)} min={1} max={20} step={1} description="Maximum number of trades allowed per hour." /> updateSetting('MIN_TIME_BETWEEN_TRADES', v)} min={0} max={3600} step={60} description="Minimum wait time between trades to prevent overtrading." />
{/* Execution */}
updateSetting('SLIPPAGE_TOLERANCE', v)} min={0.1} max={5} step={0.1} description="Maximum acceptable price slippage on market orders." />
๐Ÿงช Dry Run Mode
Simulate trades without executing. Enable for testing.
{/* Action Buttons */}
๐Ÿ’ก Save settings first, then click Restart Bot to apply changes
) } function Section({ title, description, children }: { title: string, description: string, children: React.ReactNode }) { return (

{title}

{description}

{children}
) } function Setting({ label, value, onChange, min, max, step, description }: { label: string value: number onChange: (value: number) => void min: number max: number step: number description: string }) { return (
onChange(parseFloat(e.target.value))} min={min} max={max} step={step} className="w-24 bg-slate-700 text-white px-3 py-2 rounded-lg border border-slate-600 focus:border-blue-500 focus:outline-none" />
onChange(parseFloat(e.target.value))} min={min} max={max} step={step} className="w-full h-2 bg-slate-700 rounded-lg appearance-none cursor-pointer slider" />

{description}

) }