Files
FxMathQuantWebApp/js/mq4-generator.js
T

153 lines
5.4 KiB
JavaScript
Raw Normal View History

2025-12-24 13:07:51 +03:30
/**
* 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
`;
}
}