setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); self::$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); // Enable WAL mode for high concurrency and performance self::$pdo->exec('PRAGMA journal_mode = WAL;'); self::$pdo->exec('PRAGMA foreign_keys = ON;'); self::initializeSchema(); if ($isNew || self::isAccountTableEmpty()) { self::seedInitialData(); } } return self::$pdo; } private static function initializeSchema(): void { $db = self::$pdo; // 1. Trading Accounts Table $db->exec(" CREATE TABLE IF NOT EXISTS accounts ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, broker TEXT DEFAULT 'IC Markets', account_number TEXT DEFAULT '', currency TEXT DEFAULT 'USD', initial_balance REAL NOT NULL DEFAULT 10000.0, leverage REAL DEFAULT 100.0, account_type TEXT DEFAULT 'Real', -- Real, Demo, PropFirm is_default INTEGER DEFAULT 0, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ); "); // 2. Trades Table $db->exec(" CREATE TABLE IF NOT EXISTS trades ( id INTEGER PRIMARY KEY AUTOINCREMENT, account_id INTEGER NOT NULL, ticket TEXT DEFAULT '', symbol TEXT NOT NULL, -- EURUSD, XAUUSD, GBPUSD, etc. trade_type TEXT NOT NULL, -- buy, sell lot_size REAL NOT NULL DEFAULT 0.1, open_price REAL NOT NULL, close_price REAL DEFAULT NULL, stop_loss REAL DEFAULT NULL, take_profit REAL DEFAULT NULL, open_time DATETIME NOT NULL, close_time DATETIME DEFAULT NULL, pips REAL DEFAULT 0.0, profit REAL DEFAULT 0.0, -- Net P&L in currency ($) commission REAL DEFAULT 0.0, swap REAL DEFAULT 0.0, status TEXT DEFAULT 'closed', -- open, closed strategy TEXT DEFAULT 'Price Action', timeframe TEXT DEFAULT 'M15', session TEXT DEFAULT 'London', -- London, New York, Asian, Overlap risk_reward REAL DEFAULT NULL, risk_percent REAL DEFAULT 1.0, emotion TEXT DEFAULT 'Disciplined', -- Disciplined, Greedy, Fearful, Revenge, Confident, Impatient, Neutral entry_notes TEXT DEFAULT '', exit_notes TEXT DEFAULT '', lessons TEXT DEFAULT '', screenshot_entry TEXT DEFAULT '', screenshot_exit TEXT DEFAULT '', tags TEXT DEFAULT '', created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (account_id) REFERENCES accounts(id) ON DELETE CASCADE ); "); // 3. Daily Notes / Journal Mindset Log $db->exec(" CREATE TABLE IF NOT EXISTS daily_logs ( id INTEGER PRIMARY KEY AUTOINCREMENT, account_id INTEGER NOT NULL, log_date DATE NOT NULL, notes TEXT DEFAULT '', mindset_score INTEGER DEFAULT 5, -- 1 to 5 market_condition TEXT DEFAULT 'Normal', created_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (account_id) REFERENCES accounts(id) ON DELETE CASCADE, UNIQUE(account_id, log_date) ); "); // 4. Strategies / Setups Table $db->exec(" CREATE TABLE IF NOT EXISTS strategies ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL UNIQUE, description TEXT DEFAULT '', color TEXT DEFAULT '#3b82f6', created_at DATETIME DEFAULT CURRENT_TIMESTAMP ); "); // Create indexes for fast analytical aggregations $db->exec("CREATE INDEX IF NOT EXISTS idx_trades_account ON trades(account_id);"); $db->exec("CREATE INDEX IF NOT EXISTS idx_trades_open_time ON trades(open_time);"); $db->exec("CREATE INDEX IF NOT EXISTS idx_trades_close_time ON trades(close_time);"); $db->exec("CREATE INDEX IF NOT EXISTS idx_trades_symbol ON trades(symbol);"); $db->exec("CREATE INDEX IF NOT EXISTS idx_trades_status ON trades(status);"); } private static function isAccountTableEmpty(): bool { $stmt = self::$pdo->query("SELECT COUNT(*) FROM accounts"); return ((int)$stmt->fetchColumn()) === 0; } public static function seedInitialData(): void { $db = self::$pdo; // Default Strategies $strategies = [ ['Price Action', 'Break of structure, support & resistance', '#3b82f6'], ['ICT / SMC', 'Order blocks, Fair Value Gaps (FVG) and liquidity sweeps', '#8b5cf6'], ['Trend Following', 'Moving average pullbacks and trend continuation', '#10b981'], ['Scalping', 'Fast momentum moves on M1/M5 charts', '#f59e0b'], ['Reversal / Divergence', 'RSI/MACD divergence at key supply/demand levels', '#ec4899'], ['News Trading', 'High-impact economic news releases', '#ef4444'], ]; $stmtStrat = $db->prepare("INSERT OR IGNORE INTO strategies (name, description, color) VALUES (?, ?, ?)"); foreach ($strategies as $strat) { $stmtStrat->execute($strat); } // Default Accounts $stmtAcc = $db->prepare(" INSERT INTO accounts (name, broker, account_number, currency, initial_balance, leverage, account_type, is_default) VALUES (?, ?, ?, ?, ?, ?, ?, ?) "); $stmtAcc->execute(['حساب معاملاتی اصلی (Main Live)', 'IC Markets', '8841920', 'USD', 10000.0, 100.0, 'Real', 1]); $mainAccountId = (int)$db->lastInsertId(); $stmtAcc->execute(['چالش پراپ فرم ۱۰۰ هزار دلاری (FTMO Prop)', 'FTMO', '2948173', 'USD', 100000.0, 100.0, 'PropFirm', 0]); // Seed rich realistic trading history for main account self::generateSampleTrades($mainAccountId, 10000.0); } public static function generateSampleTrades(int $accountId, float $startBalance = 10000.0): void { $db = self::$pdo; // Trade definition array: // [0:symbol, 1:type, 2:lot, 3:openPrice, 4:closePrice, 5:sl, 6:tp, 7:pips, 8:profit, 9:comm, 10:swap, 11:strat, 12:tf, 13:session, 14:rr, 15:emotion, 16:entryNotes, 17:exitNotes, 18:lessons] $tradeDataList = [ ['EURUSD', 'buy', 1.0, 1.08200, 1.08650, 1.07950, 1.08700, 45.0, 450.0, -7.0, 0.0, 'ICT / SMC', 'H1', 'London', 1.8, 'Disciplined', 'جاروب نقدینگی لندن و واکنش به FVG', 'رسیدن به هدف نقدینگی سقف روز قبل', 'پایبندی به استراتژی'], ['XAUUSD', 'buy', 0.5, 2350.20, 2368.50, 2342.00, 2370.00, 183.0, 915.0, -5.0, -2.1, 'Price Action', 'M15', 'New York', 2.2, 'Confident', 'تست مجدد سطح حمایتی ۲۳۵۰ با کندل تاییدیه پین بار', 'خروج در نزدیکی تارگت با سود عالی', 'صبر برای پولبک کلید موفقیت بود'], ['GBPUSD', 'sell', 1.2, 1.27600, 1.27150, 1.27850, 1.27000, 45.0, 540.0, -8.4, 1.5, 'Trend Following', 'M15', 'London', 1.8, 'Disciplined', 'شکست خط روند نزولی و پولبک به EMA50', 'ریسک فری شد و در تارگت ۲ بسته شد', 'مدیریت ترید عالی'], ['USDJPY', 'buy', 1.0, 154.800, 154.450, 154.400, 155.600, -35.0, -225.0, -7.0, 0.0, 'Scalping', 'M5', 'Asian', 0.0, 'Fearful', 'ورود با مومنتوم صعودی ضعیف در نشست آسیا', 'اصابت به استاپ لاس به دلیل اسپرد بالا', 'در سشن آسیا نباید روی جفت‌های کم‌نوسان بدون کاتالیزور معامله کرد'], ['EURUSD', 'sell', 1.5, 1.08900, 1.08350, 1.09150, 1.08200, 55.0, 825.0, -10.5, 0.0, 'ICT / SMC', 'M15', 'New York', 2.2, 'Disciplined', 'شکار نقدینگی سشن نیویورک و تایید با اردر بلاک خرسی', 'کست کامل سود در کف سشن لندن', 'ورود دقیق روی اوردربلاک'], ['XAUUSD', 'sell', 0.8, 2385.00, 2392.50, 2392.00, 2370.00, -75.0, -600.0, -8.0, 0.0, 'Reversal / Divergence', 'M15', 'New York', 0.0, 'Greedy', 'ورود برخلاف روند قدرتمند بدون واگرایی قطعی', 'استاپ خورد، طلا شتاب شدید صعودی داشت', 'هرگز نباید جلوی قطار سریع‌السیر ایستاد!'], ['BTCUSD', 'buy', 0.2, 63200.0, 65100.0, 62400.0, 65500.0, 1900.0, 380.0, -3.0, -0.5, 'Trend Following', 'H4', 'London', 2.4, 'Confident', 'حفظ حمایت رند ۶۳۰۰۰ و تشکیل الگوی دابل باتم', 'خروج پله‌ای در ۶۵۱۰۰', 'معامله سوینگی تمیز'], ['US30', 'buy', 0.5, 39200.0, 39650.0, 39000.0, 39700.0, 450.0, 225.0, -5.0, 0.0, 'Scalping', 'M5', 'New York', 2.2, 'Disciplined', 'اوپن سشن نیویورک و جهش شاخص داوجونز', 'خروج سریع با تارگت تعیین شده', 'مدیریت ریسک عالی'], ['GBPUSD', 'buy', 1.0, 1.26800, 1.27400, 1.26500, 1.27500, 60.0, 600.0, -7.0, 0.0, 'ICT / SMC', 'M15', 'London', 2.0, 'Disciplined', 'برگشت قیمت از ناحیه تقاضا و جاروب کف آسیا', 'تارگت لمس شد', 'برنامه معاملاتی مو به مو اجرا شد'], ['EURUSD', 'sell', 1.0, 1.08500, 1.08800, 1.08800, 1.08000, -30.0, -300.0, -7.0, 0.0, 'Price Action', 'M15', 'London', 0.0, 'Impatient', 'ورود عجولانه قبل از بسته شدن کندل ۱۵ دقیقه', 'برگشت قیمت به بالا و استاپ', 'صبر برای کلوز کندل ضروری است'], ['XAUUSD', 'buy', 0.7, 2360.00, 2378.00, 2353.00, 2380.00, 180.0, 1260.0, -7.0, -1.8, 'ICT / SMC', 'H1', 'Overlap', 2.5, 'Disciplined', 'تلاقی FVG با لول ۵۰٪ فیبوناچی در اورلپ لندن/نیویورک', 'تارگت کامل محقق شد', 'یکی از بهترین معاملات ماه'], ['AUDUSD', 'sell', 1.0, 0.66800, 0.66350, 0.67050, 0.66200, 45.0, 450.0, -7.0, 1.2, 'Trend Following', 'H1', 'Asian', 1.8, 'Neutral', 'شکست رنج قیمتی و تاییدیه با داده‌های اشتغال استرالیا', 'خروج با سود خوب', 'انطباق خوب با تحلیل فاندامنتال'], ['USDJPY', 'sell', 1.0, 156.200, 155.300, 156.600, 155.000, 90.0, 580.0, -7.0, 0.0, 'Price Action', 'H1', 'New York', 2.2, 'Disciplined', 'سقف دو قلو در تایم فریم یک ساعته با کندل اینگالف نزولی', 'خروج در حمایت کلیدی ۱۵۵.۳۰', 'معامله بسیار روان و بدون استرس'], ['EURUSD', 'buy', 1.2, 1.08300, 1.08100, 1.08050, 1.08900, -20.0, -240.0, -8.4, 0.0, 'Scalping', 'M5', 'London', 0.0, 'Neutral', 'تلاش برای گرفتن بریک اوت سریع که فیک اوت شد', 'حد ضرر نجات داد', 'ضرر کوچک و کنترل‌شده'], ['XAUUSD', 'buy', 0.6, 2375.00, 2394.00, 2368.00, 2395.00, 190.0, 1140.0, -6.0, 0.0, 'ICT / SMC', 'M15', 'New York', 2.7, 'Confident', 'سوییپ نقدینگی کف روزانه در اخبار CPI و واکنش انفجاری', 'خروج در تارگت ۲۳۹۴', 'مدیریت پوزیشن عالی حین خبر'], ['GBPUSD', 'sell', 1.0, 1.27500, 1.27100, 1.27800, 1.27000, 40.0, 400.0, -7.0, 0.0, 'Price Action', 'M15', 'London', 1.3, 'Disciplined', 'برخورد به سقف کانال نزولی', 'برداشت سود مطمئن', 'معامله استاندارد طبق پلن'], ['BTCUSD', 'sell', 0.25, 66500.0, 64200.0, 67200.0, 64000.0, 2300.0, 575.0, -3.5, 0.0, 'Reversal / Divergence', 'H4', 'New York', 3.2, 'Disciplined', 'واگرایی منفی مشهود در RSI تایم ۴ ساعته', 'ریزش عالی بیت‌کوین و سیو سود', 'نسبت ریسک به ریوارد بالای ۳'], ['US30', 'sell', 0.4, 39800.0, 39950.0, 39950.0, 39400.0, -150.0, -60.0, -4.0, 0.0, 'Scalping', 'M5', 'New York', 0.0, 'Neutral', 'ترید خلاف ترند در اوپن بازار', 'استاپ کوچک خورد', 'مدیریت ریسک عالی'], ['EURUSD', 'buy', 1.0, 1.08400, 1.08920, 1.08150, 1.09000, 52.0, 520.0, -7.0, 0.0, 'ICT / SMC', 'H1', 'London', 2.1, 'Disciplined', 'پر شدن FVG سشن لندن و چرخش روند', 'تارگت لمس شد', 'آرامش و صبر کامل'], ['XAUUSD', 'buy', 0.5, 2390.00, 2415.00, 2382.00, 2420.00, 250.0, 1250.0, -5.0, -2.5, 'Trend Following', 'H4', 'New York', 3.1, 'Confident', 'شکست سقف تاریخی قبلی و پولبک استاندارد', 'سود فوق‌العاده با تارگت بالای ۲۴۱۵', 'رعایت تمام اصول استراتژی'], ['USDJPY', 'buy', 1.0, 155.100, 155.650, 154.750, 155.800, 55.0, 355.0, -7.0, 0.0, 'Price Action', 'M15', 'Asian', 1.5, 'Disciplined', 'حمایت معتبر در سشن توکیو', 'خروج با سود خوب در شروع سشن لندن', 'ترید تمیز'], ['GBPUSD', 'buy', 1.0, 1.26900, 1.26600, 1.26600, 1.27600, -30.0, -300.0, -7.0, 0.0, 'Price Action', 'M15', 'London', 0.0, 'Fearful', 'انتشار داده‌های ضعیف بریتانیا و استاپ خوردن', 'استاپ رعایت شد', 'پایبندی به استاپ لاس نجات‌بخش بود'], ['EURUSD', 'sell', 1.0, 1.08800, 1.08300, 1.09050, 1.08200, 50.0, 500.0, -7.0, 0.0, 'ICT / SMC', 'M15', 'New York', 2.0, 'Disciplined', 'شکار نقدینگی خریداران بالای ۱.۰۸۸۰ و ریزش سریع', 'خروج در کف روز', 'ستاپ کاملاً مکانیکی و تست شده'] ]; $stmtTrade = $db->prepare(" INSERT INTO trades ( account_id, ticket, symbol, trade_type, lot_size, open_price, close_price, stop_loss, take_profit, open_time, close_time, pips, profit, commission, swap, status, strategy, timeframe, session, risk_reward, emotion, entry_notes, exit_notes, lessons, tags ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) "); $baseTime = time() - (count($tradeDataList) * 86400 * 0.9); $ticketBase = 7418290; foreach ($tradeDataList as $i => $t) { $ticket = (string)($ticketBase + $i * 17); $openTs = $baseTime + ($i * 75000) + rand(1000, 15000); $durationSec = rand(1800, 28800); $closeTs = $openTs + $durationSec; $openTimeStr = date('Y-m-d H:i:s', $openTs); $closeTimeStr = date('Y-m-d H:i:s', $closeTs); $stmtTrade->execute([ $accountId, $ticket, $t[0], $t[1], $t[2], $t[3], $t[4], $t[5], $t[6], $openTimeStr, $closeTimeStr, $t[7], $t[8], $t[9], $t[10], 'closed', $t[11], $t[12], $t[13], $t[14], $t[15], $t[16], $t[17], $t[18], 'Live,DayTrade,Forex' ]); } // Add 2 open trades $stmtTrade->execute([ $accountId, (string)($ticketBase + 991), 'XAUUSD', 'buy', 0.5, 2405.50, null, 2396.00, 2425.00, date('Y-m-d H:i:s', time() - 3600), null, 45.0, 225.0, -5.0, 0.0, 'open', 'ICT / SMC', 'H1', 'London', 2.0, 'Disciplined', 'ورود پس از شکست مقاومت ۲۴۰۰ و تثبیت بالای آن', '', '', 'OpenTrade,Swing' ]); $stmtTrade->execute([ $accountId, (string)($ticketBase + 992), 'EURUSD', 'sell', 1.0, 1.08620, null, 1.08850, 1.08100, date('Y-m-d H:i:s', time() - 7200), null, 12.0, 120.0, -7.0, 0.0, 'open', 'Price Action', 'M15', 'London', 2.2, 'Confident', 'تشکیل الگوی پوشای نزولی در لول مقاومت روزانه', '', '', 'OpenTrade,Intraday' ]); } }