import { useState, useEffect, useRef } from "react"; import { LineChart, Line, XAxis, YAxis, Tooltip, ResponsiveContainer, ReferenceLine } from "recharts"; // ─── Simulated live data (replace with real MT5 API/websocket in production) ─── function useSimulatedBot(strategy, params) { const [log, setLog] = useState([]); const [trades, setTrades] = useState([]); const [price, setPrice] = useState(1.08542); const [priceHistory, setPriceHistory] = useState(() => Array.from({ length: 60 }, (_, i) => ({ t: i, price: 1.0854 + (Math.random() - 0.5) * 0.003, })) ); const [equity, setEquity] = useState(10000); const [running, setRunning] = useState(false); const tickRef = useRef(0); useEffect(() => { if (!running) return; const id = setInterval(() => { tickRef.current++; const t = tickRef.current; // Simulate price walk setPrice((p) => { const next = +(p + (Math.random() - 0.499) * 0.0003).toFixed(5); setPriceHistory((h) => [...h.slice(-99), { t, price: next }]); return next; }); // Occasionally fire a signal if (t % 8 === 0) { const side = Math.random() > 0.5 ? "BUY" : "SELL"; const entry = price; const pnl = (Math.random() - 0.45) * 30; const trade = { id: t, time: new Date().toLocaleTimeString(), side, entry: entry.toFixed(5), pnl: pnl.toFixed(2), status: pnl > 0 ? "WIN" : "LOSS", }; setTrades((prev) => [trade, ...prev].slice(0, 30)); setEquity((e) => +(e + pnl).toFixed(2)); setLog((l) => [ `[${trade.time}] Signal: ${side} @ ${entry.toFixed(5)} → P&L: $${pnl.toFixed(2)}`, ...l, ].slice(0, 100) ); } }, 800); return () => clearInterval(id); }, [running, price]); return { log, trades, price, priceHistory, equity, running, setRunning }; } // ─── Components ─────────────────────────────────────────────────────────────── const STRATEGIES = ["MA_CROSSOVER", "RSI", "BOLLINGER", "MACD"]; const defaultParams = { MA_CROSSOVER: { fast_ma: 10, slow_ma: 50 }, RSI: { rsi_period: 14, rsi_overbought: 70, rsi_oversold: 30 }, BOLLINGER: { bb_period: 20, bb_std: 2.0 }, MACD: { macd_fast: 12, macd_slow: 26, macd_signal: 9 }, }; function Badge({ children, color }) { const colors = { green: "bg-emerald-500/20 text-emerald-400 border-emerald-500/30", red: "bg-red-500/20 text-red-400 border-red-500/30", blue: "bg-sky-500/20 text-sky-400 border-sky-500/30", yellow: "bg-amber-500/20 text-amber-400 border-amber-500/30", }; return ( {children} ); } function StatCard({ label, value, sub, color = "white" }) { const textColor = { white: "text-white", green: "text-emerald-400", red: "text-red-400" }[color]; return (
{label} {value} {sub && {sub}}
); } function ParamInput({ label, value, onChange }) { return ( ); } // ─── Main App ────────────────────────────────────────────────────────────────── export default function App() { const [strategy, setStrategy] = useState("MA_CROSSOVER"); const [params, setParams] = useState(defaultParams); const [symbol, setSymbol] = useState("EURUSD"); const [lotSize, setLotSize] = useState(0.1); const [slPips, setSlPips] = useState(30); const [tpPips, setTpPips] = useState(60); const [dryRun, setDryRun] = useState(true); const { log, trades, price, priceHistory, equity, running, setRunning } = useSimulatedBot(strategy, params[strategy]); const winRate = trades.length ? ((trades.filter((t) => t.status === "WIN").length / trades.length) * 100).toFixed(1) : "—"; const totalPnl = trades.reduce((s, t) => s + parseFloat(t.pnl), 0).toFixed(2); const equityColor = equity >= 10000 ? "green" : "red"; function updateParam(strat, key, val) { setParams((p) => ({ ...p, [strat]: { ...p[strat], [key]: +val } })); } return (
{/* Google Fonts */} {/* Header */}

ForexBot MT5

MetaTrader 5 · Live Trading Dashboard

{dryRun ? "DRY RUN" : "LIVE"} {running ? "● RUNNING" : "○ STOPPED"}
{/* ── Sidebar Config ── */} {/* ── Main Panel ── */}
{/* Stats row */}
= 0 ? "green" : "red"} />
{/* Price chart */}
{symbol} Price Feed Last 100 ticks
[v.toFixed(5), "Price"]} labelFormatter={() => ""} />
{/* Trade history */}
Trade History
{trades.length === 0 ? (
No trades yet. Start the bot to begin.
) : ( {["Time","Side","Entry","P&L","Result"].map(h=>( ))} {trades.map((t) => ( ))}
{h}
{t.time} {t.side} {t.entry} = 0 ? "text-emerald-400" : "text-red-400"}`}> {parseFloat(t.pnl) >= 0 ? "+" : ""}${t.pnl} {t.status}
)}
{/* Log */}
Bot Log
{log.length === 0 ? ( Waiting for signals… ) : ( log.map((l, i) => (
{l}
)) )}
); }