Files
2025-12-26 10:59:31 +03:30

330 lines
11 KiB
JavaScript

// MQ4 Converter
class MQ4Converter {
constructor(strategy) {
this.strategy = strategy;
this.parser = new RuleParser();
}
generate() {
const { parameters, buy_rules, sell_rules } = this.strategy;
const symbol = parameters.symbol || 'EURUSD';
const atrPeriod = parameters.atr_period || 14;
const slMultiplier = parameters.sl_multiplier || 2.0;
const tpMultiplier = parameters.tp_multiplier || 3.0;
// Generate random 6-digit magic number
const magicNumber = Math.floor(100000 + Math.random() * 900000);
const buyConditions = this.parser.parseRules(buy_rules, 'mql');
// SELL rules use inverted operators
const sellConditions = this.parser.parseRulesInverted(buy_rules, 'mql');
return `//+------------------------------------------------------------------+
//| Strategy_${symbol}.mq4 |
//| Generated by Strategy Converter |
//+------------------------------------------------------------------+
#property copyright "FxMath Quant"
#property link "https://fxmath.com"
#property version "1.00"
#property strict
//=== TRADE SETTINGS ===
input double LotSize = 0.1; // Lot Size
input int ATR_Period = ${atrPeriod}; // ATR Period
input double SL_Multiplier = ${slMultiplier.toFixed(2)}; // SL ATR Multiplier
input double TP_Multiplier = ${tpMultiplier.toFixed(2)}; // TP ATR Multiplier
input int MagicNumber = ${magicNumber}; // Magic Number
input string TradeComment = "FxMath EA"; // Trade Comment
input int Slippage = 3; // Slippage
//=== SL/TP SETTINGS ===
input bool EnableHardSL = true; // Enable Hard Stop Loss
input bool EnableHardTP = true; // Enable Hard Take Profit
//=== TRAILING STOP ===
input bool EnableTrailing = false; // Enable Trailing Stop
input double TrailingStart = 30; // Trailing Start (pips)
input double TrailingStep = 10; // Trailing Step (pips)
//=== BREAKEVEN ===
input bool EnableBreakeven = false; // Enable Breakeven
input double BreakevenStart = 20; // Breakeven Start (pips)
input double BreakevenOffset = 2; // Breakeven Offset (pips)
//=== TIME FILTER ===
input bool EnableTimeFilter = false; // Enable Time Filter
input int StartHour = 8; // Start Hour (Server Time)
input int StartMinute = 0; // Start Minute
input int EndHour = 22; // End Hour (Server Time)
input int EndMinute = 0; // End Minute
//=== SIGNAL SETTINGS ===
input bool CloseOnOpposite = false; // Close Trade on Opposite Signal
//=== DISPLAY SETTINGS ===
input bool ShowChartInfo = true; // Show Info on Chart
// Global Variables
double atrValue;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
Print("Strategy EA initialized for ${symbol}");
Print("Magic Number: ", MagicNumber);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
Print("Strategy EA deinitialized");
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Calculate ATR
atrValue = iATR(Symbol(), 0, ATR_Period, 1);
// Check for open positions
bool hasPosition = false;
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
hasPosition = true;
ManagePosition();
break;
}
}
}
// If no position, check for entry signals
if(!hasPosition)
{
// Check time filter
if(EnableTimeFilter && !IsTimeAllowed())
return;
// Check Buy Signal
if(CheckBuySignal())
{
OpenBuyOrder();
}
// Check Sell Signal
else if(CheckSellSignal())
{
OpenSellOrder();
}
}
// Display chart info
if(ShowChartInfo)
DisplayChartInfo();
}
//+------------------------------------------------------------------+
//| Check if current time is allowed for trading |
//+------------------------------------------------------------------+
bool IsTimeAllowed()
{
int currentHour = Hour();
int currentMinute = Minute();
int currentMinutes = currentHour * 60 + currentMinute;
int startMinutes = StartHour * 60 + StartMinute;
int endMinutes = EndHour * 60 + EndMinute;
if(startMinutes < endMinutes)
return (currentMinutes >= startMinutes && currentMinutes < endMinutes);
else
return (currentMinutes >= startMinutes || currentMinutes < endMinutes);
}
//+------------------------------------------------------------------+
//| Manage existing position |
//+------------------------------------------------------------------+
void ManagePosition()
{
if(!OrderSelect(0, SELECT_BY_POS, MODE_TRADES))
return;
int orderType = OrderType();
double orderOpenPrice = OrderOpenPrice();
double orderSL = OrderStopLoss();
double orderTP = OrderTakeProfit();
// Check for opposite signal
if(CloseOnOpposite)
{
if(orderType == OP_BUY && CheckSellSignal())
{
if(!OrderClose(OrderTicket(), OrderLots(), Bid, Slippage, clrRed))
Print("Error closing buy order: ", GetLastError());
return;
}
else if(orderType == OP_SELL && CheckBuySignal())
{
if(!OrderClose(OrderTicket(), OrderLots(), Ask, Slippage, clrGreen))
Print("Error closing sell order: ", GetLastError());
return;
}
}
double currentPrice = (orderType == OP_BUY) ? Bid : Ask;
double point = Point;
double pipValue = point * 10;
// Breakeven
if(EnableBreakeven)
{
double profit = (orderType == OP_BUY) ?
(currentPrice - orderOpenPrice) :
(orderOpenPrice - currentPrice);
if(profit >= BreakevenStart * pipValue)
{
double newSL = orderOpenPrice + (BreakevenOffset * pipValue *
((orderType == OP_BUY) ? 1 : -1));
if((orderType == OP_BUY && newSL > orderSL) ||
(orderType == OP_SELL && (orderSL == 0 || newSL < orderSL)))
{
if(!OrderModify(OrderTicket(), orderOpenPrice, newSL, orderTP, 0, clrBlue))
Print("Error modifying order for breakeven: ", GetLastError());
}
}
}
// Trailing Stop
if(EnableTrailing)
{
double profit = (orderType == OP_BUY) ?
(currentPrice - orderOpenPrice) :
(orderOpenPrice - currentPrice);
if(profit >= TrailingStart * pipValue)
{
double newSL = currentPrice - (TrailingStep * pipValue *
((orderType == OP_BUY) ? 1 : -1));
if((orderType == OP_BUY && newSL > orderSL) ||
(orderType == OP_SELL && (orderSL == 0 || newSL < orderSL)))
{
if(!OrderModify(OrderTicket(), orderOpenPrice, newSL, orderTP, 0, clrBlue))
Print("Error modifying order for trailing stop: ", GetLastError());
}
}
}
}
//+------------------------------------------------------------------+
//| Display chart information |
//+------------------------------------------------------------------+
void DisplayChartInfo()
{
string info = "\\n=== " + TradeComment + " ===\\n";
info += "Symbol: " + Symbol() + "\\n";
info += "Magic: " + IntegerToString(MagicNumber) + "\\n";
bool hasPosition = false;
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
hasPosition = true;
info += "Position: " + (OrderType() == OP_BUY ? "BUY" : "SELL") + "\\n";
info += "Profit: " + DoubleToStr(OrderProfit(), 2) + "\\n";
break;
}
}
}
if(!hasPosition)
info += "No Position\\n";
Comment(info);
}
//+------------------------------------------------------------------+
//| Check Buy Signal |
//+------------------------------------------------------------------+
bool CheckBuySignal()
{
return (${buyConditions.join(' &&\n ')});
}
//+------------------------------------------------------------------+
//| Check Sell Signal |
//+------------------------------------------------------------------+
bool CheckSellSignal()
{
return (${sellConditions.join(' &&\n ')});
}
//+------------------------------------------------------------------+
//| Open Buy Order |
//+------------------------------------------------------------------+
void OpenBuyOrder()
{
double price = Ask;
double sl = EnableHardSL ? price - (atrValue * SL_Multiplier) : 0;
double tp = EnableHardTP ? price + (atrValue * TP_Multiplier) : 0;
sl = (sl > 0) ? NormalizeDouble(sl, Digits) : 0;
tp = (tp > 0) ? NormalizeDouble(tp, Digits) : 0;
int ticket = OrderSend(Symbol(), OP_BUY, LotSize, price, Slippage, sl, tp,
TradeComment, MagicNumber, 0, clrGreen);
if(ticket > 0)
{
Print("Buy order opened at ", price, " SL: ", sl, " TP: ", tp);
}
else
{
Print("Error opening buy order: ", GetLastError());
}
}
//+------------------------------------------------------------------+
//| Open Sell Order |
//+------------------------------------------------------------------+
void OpenSellOrder()
{
double price = Bid;
double sl = EnableHardSL ? price + (atrValue * SL_Multiplier) : 0;
double tp = EnableHardTP ? price - (atrValue * TP_Multiplier) : 0;
sl = (sl > 0) ? NormalizeDouble(sl, Digits) : 0;
tp = (tp > 0) ? NormalizeDouble(tp, Digits) : 0;
int ticket = OrderSend(Symbol(), OP_SELL, LotSize, price, Slippage, sl, tp,
TradeComment, MagicNumber, 0, clrRed);
if(ticket > 0)
{
Print("Sell order opened at ", price, " SL: ", sl, " TP: ", tp);
}
else
{
Print("Error opening sell order: ", GetLastError());
}
}
//+------------------------------------------------------------------+
`;
}
}
window.MQ4Converter = MQ4Converter;