/** * MQ4 Code Generator - Generates MetaTrader 4 Expert Advisor code */ class MQ4Generator { constructor(strategy, strategyName) { this.strategy = strategy; this.name = strategyName || this.generateName(); } generateName() { const pf = this.strategy.metrics.profitFactor.toFixed(2).replace('.', '_'); const wr = Math.round(this.strategy.metrics.winRate); const timestamp = new Date().toISOString().slice(0, 10).replace(/-/g, ''); return `FxMath_PF${pf}_WR${wr}_${timestamp}`; } generate() { return `//+------------------------------------------------------------------+ //| ${this.name}.mq4 | //| Generated by FxMathQuant Web | //| https://fxmathquant.com | //+------------------------------------------------------------------+ #property copyright "FxMathQuant" #property link "https://fxmathquant.com" #property version "1.00" #property strict //--- Input Parameters input double LotSize = 0.01; // Lot size input int MagicNumber = ${Math.floor(Math.random() * 9000) + 1000}; // Magic number input int ATR_Period = ${this.strategy.atrPeriod}; // ATR period input double SL_Multiplier = ${this.strategy.slMultiplier.toFixed(2)}; // Stop Loss multiplier input double TP_Multiplier = ${this.strategy.tpMultiplier.toFixed(2)}; // Take Profit multiplier input int Slippage = 3; // Slippage in points //--- Global Variables int ticket = 0; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { Print("${this.name} initialized"); Print("Strategy Performance: PF=${this.strategy.metrics.profitFactor.toFixed(2)}, WR=${this.strategy.metrics.winRate.toFixed(1)}%"); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { Print("${this.name} stopped"); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { // Check if we already have an open position if(OrdersTotal() > 0) { for(int i = 0; i < OrdersTotal(); i++) { if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber) return; // Position already open } } } // Calculate ATR double atr = iATR(Symbol(), Period(), ATR_Period, 0); if(atr == 0) return; // Check for BUY signal if(CheckBuySignal()) { double entry = Ask; double sl = entry - (atr * SL_Multiplier); double tp = entry + (atr * TP_Multiplier); // Normalize prices sl = NormalizeDouble(sl, Digits); tp = NormalizeDouble(tp, Digits); // Open BUY order ticket = OrderSend(Symbol(), OP_BUY, LotSize, entry, Slippage, sl, tp, "${this.name}", MagicNumber, 0, clrGreen); if(ticket > 0) Print("BUY order opened: ", ticket, " @ ", entry, " SL:", sl, " TP:", tp); else Print("Error opening BUY order: ", GetLastError()); } } //+------------------------------------------------------------------+ //| Check BUY signal based on strategy rules | //+------------------------------------------------------------------+ bool CheckBuySignal() { ${this.generateRulesCode()} return true; // All rules passed } ${this.generateHelperFunctions()} //+------------------------------------------------------------------+ `; } generateRulesCode() { return this.strategy.rules.map((rule, index) => { const condition = this.ruleToMQ4(rule); return ` // Rule ${index + 1} if(!(${condition})) return false;`; }).join('\n'); } ruleToMQ4(rule) { if (rule.type === 'simple') { const left = this.priceToMQ4(rule.left.price, rule.left.shift); const right = this.priceToMQ4(rule.right.price, rule.right.shift); return `${left} ${rule.operator} ${right}`; } else { // Arithmetic rule const left1 = this.priceToMQ4(rule.left.price1, rule.left.shift1); const left2 = this.priceToMQ4(rule.left.price2, rule.left.shift2); const right = this.priceToMQ4(rule.right.price, rule.right.shift); return `(${left1} ${rule.left.op} ${left2}) ${rule.operator} (${right} * ${rule.right.multiplier})`; } } priceToMQ4(priceType, shift) { const type = priceType.charAt(0).toUpperCase() + priceType.slice(1); return `i${type}(Symbol(), Period(), ${shift})`; } generateHelperFunctions() { return `//+------------------------------------------------------------------+ //| Helper Functions | //+------------------------------------------------------------------+ // Add any additional helper functions here `; } }