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

343 lines
12 KiB
JavaScript

// MQ5 Converter
class MQ5Converter {
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, 'mq5');
// SELL rules use inverted operators
const sellConditions = this.parser.parseRulesInverted(buy_rules, 'mq5');
return `//+------------------------------------------------------------------+
//| Strategy_${symbol}.mq5 |
//| Generated by Strategy Converter |
//+------------------------------------------------------------------+
#property copyright "FxMath Quant"
#property link "https://fxmath.com"
#property version "1.00"
#include <Trade\\Trade.mqh>
//=== TRADING SETTINGS ===
input group "=== 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 ulong MagicNumber = ${magicNumber}; // Magic Number
input string TradeComment = "FxMath EA"; // Trade Comment
input int Slippage = 3; // Slippage
//=== SL/TP SETTINGS ===
input group "=== SL/TP Settings ==="
input bool EnableHardSL = true; // Enable Hard Stop Loss
input bool EnableHardTP = true; // Enable Hard Take Profit
//=== TRAILING STOP ===
input group "=== 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 group "=== Breakeven ==="
input bool EnableBreakeven = false; // Enable Breakeven
input double BreakevenStart = 20; // Breakeven Start (pips)
input double BreakevenOffset = 2; // Breakeven Offset (pips)
//=== TIME FILTER ===
input group "=== 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 group "=== Signal Settings ==="
input bool CloseOnOpposite = false; // Close Trade on Opposite Signal
//=== DISPLAY SETTINGS ===
input group "=== Display Settings ==="
input bool ShowChartInfo = true; // Show Info on Chart
// Global Variables
CTrade trade;
int atrHandle;
double atrBuffer[];
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Set trade parameters
trade.SetExpertMagicNumber(MagicNumber);
trade.SetDeviationInPoints(Slippage);
trade.SetTypeFilling(ORDER_FILLING_FOK);
// Create ATR indicator handle
atrHandle = iATR(_Symbol, PERIOD_CURRENT, ATR_Period);
if(atrHandle == INVALID_HANDLE)
{
Print("Error creating ATR indicator");
return(INIT_FAILED);
}
ArraySetAsSeries(atrBuffer, true);
Print("Strategy EA initialized for ${symbol}");
Print("Magic Number: ", MagicNumber);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
if(atrHandle != INVALID_HANDLE)
IndicatorRelease(atrHandle);
Print("Strategy EA deinitialized");
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Copy ATR values
if(CopyBuffer(atrHandle, 0, 0, 2, atrBuffer) < 2)
{
Print("Error copying ATR buffer");
return;
}
double atrValue = atrBuffer[1];
// Check if we have an open position
if(PositionSelect(_Symbol))
{
// Position exists - manage it
ManagePosition(atrValue);
}
else
{
// No position - check for entry signals
// Check time filter
if(EnableTimeFilter && !IsTimeAllowed())
return;
// Check Buy Signal
if(CheckBuySignal())
{
OpenBuyOrder(atrValue);
}
// Check Sell Signal
else if(CheckSellSignal())
{
OpenSellOrder(atrValue);
}
}
// Display chart info
if(ShowChartInfo)
DisplayChartInfo();
}
//+------------------------------------------------------------------+
//| Check if current time is allowed for trading |
//+------------------------------------------------------------------+
bool IsTimeAllowed()
{
MqlDateTime dt;
TimeToStruct(TimeCurrent(), dt);
int currentMinutes = dt.hour * 60 + dt.min;
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(double atrValue)
{
if(!PositionSelect(_Symbol))
return;
long posType = PositionGetInteger(POSITION_TYPE);
double posOpenPrice = PositionGetDouble(POSITION_PRICE_OPEN);
double posSL = PositionGetDouble(POSITION_SL);
double posTP = PositionGetDouble(POSITION_TP);
// Check for opposite signal
if(CloseOnOpposite)
{
if(posType == POSITION_TYPE_BUY && CheckSellSignal())
{
trade.PositionClose(_Symbol);
return;
}
else if(posType == POSITION_TYPE_SELL && CheckBuySignal())
{
trade.PositionClose(_Symbol);
return;
}
}
double currentPrice = (posType == POSITION_TYPE_BUY) ?
SymbolInfoDouble(_Symbol, SYMBOL_BID) :
SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
double pipValue = point * 10;
// Breakeven
if(EnableBreakeven)
{
double profit = (posType == POSITION_TYPE_BUY) ?
(currentPrice - posOpenPrice) :
(posOpenPrice - currentPrice);
if(profit >= BreakevenStart * pipValue)
{
double newSL = posOpenPrice + (BreakevenOffset * pipValue *
((posType == POSITION_TYPE_BUY) ? 1 : -1));
if((posType == POSITION_TYPE_BUY && newSL > posSL) ||
(posType == POSITION_TYPE_SELL && (posSL == 0 || newSL < posSL)))
{
trade.PositionModify(_Symbol, newSL, posTP);
}
}
}
// Trailing Stop
if(EnableTrailing)
{
double profit = (posType == POSITION_TYPE_BUY) ?
(currentPrice - posOpenPrice) :
(posOpenPrice - currentPrice);
if(profit >= TrailingStart * pipValue)
{
double newSL = currentPrice - (TrailingStep * pipValue *
((posType == POSITION_TYPE_BUY) ? 1 : -1));
if((posType == POSITION_TYPE_BUY && newSL > posSL) ||
(posType == POSITION_TYPE_SELL && (posSL == 0 || newSL < posSL)))
{
trade.PositionModify(_Symbol, newSL, posTP);
}
}
}
}
//+------------------------------------------------------------------+
//| Display chart information |
//+------------------------------------------------------------------+
void DisplayChartInfo()
{
string info = "\\n=== " + TradeComment + " ===\\n";
info += "Symbol: " + _Symbol + "\\n";
info += "Magic: " + IntegerToString(MagicNumber) + "\\n";
if(PositionSelect(_Symbol))
{
info += "Position: " + EnumToString((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE)) + "\\n";
info += "Profit: " + DoubleToString(PositionGetDouble(POSITION_PROFIT), 2) + "\\n";
}
else
{
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 atrValue)
{
double price = SymbolInfoDouble(_Symbol, SYMBOL_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;
if(trade.Buy(LotSize, _Symbol, price, sl, tp, TradeComment))
{
Print("Buy order opened at ", price, " SL: ", sl, " TP: ", tp);
}
else
{
Print("Error opening buy order: ", GetLastError());
}
}
//+------------------------------------------------------------------+
//| Open Sell Order |
//+------------------------------------------------------------------+
void OpenSellOrder(double atrValue)
{
double price = SymbolInfoDouble(_Symbol, SYMBOL_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;
if(trade.Sell(LotSize, _Symbol, price, sl, tp, TradeComment))
{
Print("Sell order opened at ", price, " SL: ", sl, " TP: ", tp);
}
else
{
Print("Error opening sell order: ", GetLastError());
}
}
//+------------------------------------------------------------------+
`;
}
}
window.MQ5Converter = MQ5Converter;