Puga/Puga.mq5
super.admin cb1aa93a0a convert
2025-05-30 16:18:30 +02:00

389 lines
38 KiB
MQL5

//+------------------------------------------------------------------+
//| Includes |
//+------------------------------------------------------------------+
//test
#include <Trade\Trade.mqh>
#include <Trade\SymbolInfo.mqh>
#include <Trade\AccountInfo.mqh>
#include "PugaFiles\Strategy.mqh"
#include "PugaFiles\RangerNew.mqh"
//+------------------------------------------------------------------+
//| Variables |
//+------------------------------------------------------------------+
//доступ к размещению ордеров
CTrade trade;
CAccountInfo account;
double balance = AccountInfoDouble(ACCOUNT_BALANCE);
//доступ к данным о ценах ([0] - для текущей свечи)
//MqlRates priceInfo[];
//объекты хранящие данные по каждому направлению
Strategy hell[], paradise[];
//функционал доступа к мультивалютной торговле
input string tradeSymbols = "EURUSD|EURGBP|AUDUSD|NZDJPY|AUDCHF|NZDUSD|GBPJPY|AUDCAD|EURAUD|USDJPY|USDCHF|CADCHF|GBPCHF|EURCAD|USDCAD"; //Current, for current symbol, else "AUDUSD|EURUSD" format
input bool radio = true;//Radio Switcher
input ENUM_TIMEFRAMES timeFrame1 = PERIOD_M1;//in TF
input ENUM_TIMEFRAMES timeFrame2 = PERIOD_M1;//out TF
input int rangesToCalc = 2;
input double coefstart = 0.6;//Start Lot Mult
input double corrStrength = 0.99;//Signal Quality
//input double pairWeak = -0.9;//Pair Corr Weakness
//input double takeProfit = 1.1;//Take Profit %
input double gagaPercent = 2.1;
input double pairStrength = -0.74;//Pair Corr Quality
input double tickStrength = -0.95;//Tick Corr Quality
input int counting = 200;//Tick quantity
//input double spreadSurge = 0.5;
//input double drawDown = 5;
int numberOfTradebleSymbols, symbolToTrade, symbolSub;
string symbolArray[];
MqlRates symbol1[], symbol2[], symbol1tmp[], symbol2tmp[];
//переменные проверки на доступность рынка
MqlDateTime time;
bool open = true;
double paraLot = 0;
double hellLot = 0;
double pairCorr = 0;
double tickCorr = 0;
double spreadX = 0;
double spreadM = 0;
int bars = 0;
double tick1Position = 0;
double tick2Position = 0;
vector symbol1v, symbol2v, tick1v, tick2v;
//Остальные вспомогательные переменные
Ranger ranger;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
if(StringCompare(tradeSymbols, "Current", false) == 0)
{
//Если введен "current", будет использоваться текущий символ из терминала
ArrayResize(symbolArray, 1);
symbolArray[0] = _Symbol;
numberOfTradebleSymbols = 1;
}
else
{
//Заполняем массив symbolArray стрингами символов согласно их введенному количеству
numberOfTradebleSymbols = StringSplit(tradeSymbols, '|', symbolArray);
Print("Total Symbols: ", numberOfTradebleSymbols);
ArrayPrint(symbolArray);
}
ArrayResize(hell, numberOfTradebleSymbols);
ArrayResize(paradise, numberOfTradebleSymbols);
ArraySetAsSeries(symbol1,true);
ArraySetAsSeries(symbol2,true);
ArraySetAsSeries(symbol1tmp,true);
ArraySetAsSeries(symbol2tmp,true);
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
ENUM_TIMEFRAMES tf = timeFrame1;
if(PositionsTotal() > 0)
{
tf = timeFrame2;
}
else
{
tf = timeFrame1;
}
//получим данные об актуальном тике в соответствующую структуру
MqlTick tick;
//условия в которых разрешена торговля на рынке
TimeToStruct(TimeCurrent(), time);
datetime timenow = TimeCurrent();
open = true;
if((time.hour == 0 && time.min < 07) || (time.hour == 23 && time.min > 53))
{
open = false;
}
//проверка по какому символу пришел тик
for(int i =0; i < numberOfTradebleSymbols; i++)
{
SymbolInfoTick(symbolArray[i], tick);
if(tick.time <= timenow)
{
symbolToTrade = i;
symbolSub = (i == 1 ? 0 : 1);//arraysize(symbolarray)-i
//Print("Now trading ", symbolArray[symbolToTrade], " ask: ", tick.ask, " bid: ", tick.bid);
//dve skobki } /n }
MqlRates daily[];
ArraySetAsSeries(daily,true);
CopyRates(symbolArray[symbolToTrade],PERIOD_H1,0,1,daily);
int currBars = Bars(symbolArray[symbolToTrade],tf,daily[0].time,TimeCurrent());
if(bars != currBars)// && PositionsTotal() == 0)
{
symbol1v.CopyRates(symbolArray[symbolToTrade],tf,COPY_RATES_CLOSE,0,240);
symbol2v.CopyRates(symbolArray[symbolSub],tf,COPY_RATES_CLOSE,0,240);
tick1v.CopyTicks(symbolArray[symbolToTrade],COPY_TICKS_LAST,0,counting);
//Print(tick1v);
tick2v.CopyTicks(symbolArray[symbolSub],COPY_TICKS_LAST,0,counting);
//Print(tick2v);
pairCorr = symbol1v.CorrCoef(symbol2v);
tickCorr = tick1v.CorrCoef(tick2v);
if(tick1v.Size() > 0 && tick2v.Size() > 0)
{
double tick1mid = tick1v.Mean();
double tick2mid = tick2v.Mean();
tick1Position = tick1mid - tick1v[tick1v.Size()-1];
tick2Position = tick2mid - tick2v[tick2v.Size()-1];
//Prove of correlation position
//Print("Pair corr: ", pairCorr, " Tick corr: ", tickCorr);
//Print(tick1mid," - ",tick1v[tick1v.Size()-1]," = ",tick1Position);
//Print(tick2mid," - ",tick2v[tick2v.Size()-1]," = ",tick2Position);
}
bars = currBars;
}
//+------------------------------------------------------------------+
//| CORE |
//+------------------------------------------------------------------+
double signal = ranger.Rrange(symbolArray[symbolToTrade],tf,rangesToCalc);
double bid = NormalizeDouble(SymbolInfoDouble(symbolArray[symbolToTrade], SYMBOL_BID), _Digits);
double ask = NormalizeDouble(SymbolInfoDouble(symbolArray[symbolToTrade], SYMBOL_ASK), _Digits);
double bidSub = NormalizeDouble(SymbolInfoDouble(symbolArray[symbolSub], SYMBOL_BID), _Digits);
double askSub = NormalizeDouble(SymbolInfoDouble(symbolArray[symbolSub], SYMBOL_ASK), _Digits);
double hellTot = 0;
double paraTot = 0;
double maxHell = 0;
double maxPara = 0;
double hellGlob = 0;
double paraGlob = 0;
if(PositionsTotal() > 0)
{
if(ArraySize(hell[symbolToTrade].ID) > 0)
{
for(int i=0; i<ArraySize(hell[symbolToTrade].ID); i++)
{
PositionSelectByTicket(hell[symbolToTrade].ID[i]);
hellTot = hellTot + PositionGetDouble(POSITION_PROFIT);
}
}
if(ArraySize(paradise[symbolToTrade].ID) > 0)
{
for(int i=0; i<ArraySize(paradise[symbolToTrade].ID); i++)
{
PositionSelectByTicket(paradise[symbolToTrade].ID[i]);
paraTot = paraTot + PositionGetDouble(POSITION_PROFIT);
}
}
for(int i=PositionsTotal() ; i>=0; i--)
{
ulong marker = PositionGetTicket(i);
PositionSelectByTicket(marker);
string comm = PositionGetString(POSITION_COMMENT);
if(StringCompare(comm, "hell", false) == 0)
{
maxHell = maxHell + PositionGetDouble(POSITION_VOLUME);
hellGlob = hellGlob + PositionGetDouble(POSITION_PROFIT);
}
else
if(StringCompare(comm, "paradise", false) == 0)
{
maxPara = maxPara + PositionGetDouble(POSITION_VOLUME);
paraGlob = paraGlob + PositionGetDouble(POSITION_PROFIT);
}
}
}
else
{
hellTot = 0;
paraTot = 0;
maxHell = 0;
maxPara = 0;
hellGlob = 0;
paraGlob = 0;
}
//---Global Cross Profit
//if(hellGlob > MathAbs(paraTot)*(1 + takeProfit/100) && open && ArraySize(paradise[symbolToTrade].ID) > 0 && maxPara <= paradise[symbolToTrade].TotalSize()*2)
// {
// paradise[symbolToTrade].StrategyClear();
// for(int i=PositionsTotal() ; i>=0; i--)
// {
// ulong marker = PositionGetTicket(i);
// PositionSelectByTicket(marker);
// string comm = PositionGetString(POSITION_COMMENT);
// if(StringCompare(comm, "hell", false) == 0)
// {
// trade.PositionClose(marker);
// }
// }
// hell[symbolToTrade].Updater(symbolArray[symbolToTrade],"hell",ArraySize(hell[symbolToTrade].ID));
// Print("Global Hell Profit ", hellGlob, " >>>>> ", paraTot, " pairCorr ", pairCorr, " tickCorr ", tickCorr);//, " Position between: ", (delta/spreadX+spreadM/delta)/2);
// }
//if(paraGlob > MathAbs(hellTot)*(1 + takeProfit/100) && open && ArraySize(hell[symbolToTrade].ID) > 0 && maxHell <= hell[symbolToTrade].TotalSize()*2)
// {
// hell[symbolToTrade].StrategyClear();
// for(int i=PositionsTotal() ; i>=0; i--)
// {
// ulong marker = PositionGetTicket(i);
// PositionSelectByTicket(marker);
// string comm = PositionGetString(POSITION_COMMENT);
// if(StringCompare(comm, "paradise", false) == 0)
// {
// trade.PositionClose(marker);
// }
// }
// paradise[symbolToTrade].Updater(symbolArray[symbolToTrade],"paradise",ArraySize(paradise[symbolToTrade].ID));
// Print("Global Paradise Profit ", paraGlob, " >>>>> ", hellTot, " pairCorr ", pairCorr, " tickCorr ", tickCorr);//, " Position between: ", (delta/spreadX+spreadM/delta)/2);
// }
//END TREND CHECK
//POSITION GENERATOR
//---
balance = PositionsTotal() > 0 ? balance : AccountInfoDouble(ACCOUNT_BALANCE);
//start
//combination of < > define the strategy:
// a. conv. pairCorr > is for positivly correlated pairs only, for non correlated is defined as b. diver <
// a: tick position > 0 for buy < 0 for sale
// b: tick position < 0 for buy > 0 for sale
// a: convergence to regression line of ultra correlation
// b: divergence from regression line of ultra correlation
// -0.95 tickcorr is the most valuable filter of the correlation
// still it is obligitary to continiously check trend correlation for advanced filter
// notes:
// best practice to let strategy open enough trades by set higher paircorr less (<) then pairstrength
// keep formula a. below:
// a: < > < b:
// possible explanation: require amount of pair correlation to cut highly correlated intervals where impossible to get profit
// and stick to converge tactics
if(PositionsTotal() == 0 && open && pairCorr < pairStrength && tickCorr < tickStrength)// > pair base (< for 0.74 / -0.95)
{
double lotstart = NormalizeDouble(MathAbs(AccountInfoDouble(ACCOUNT_BALANCE)*0.4/numberOfTradebleSymbols/16/100*coefstart), 2);
if(tick1Position > 0)// ">" lower then mid => buy (base) (> for 0.74 / -0.95)
{
trade.Buy(lotstart, symbolArray[symbolToTrade], ask, 0, 0, "hell");//hell[symbolToTrade].TotalSize()
trade.Sell(lotstart, symbolArray[symbolSub], bidSub, 0, 0, "paradise");//paradise[symbolToTrade].TotalSize()
}
else
if(tick1Position < 0)// "<" is higher then mid => sell (< for 0.74 / -0.95)
{
trade.Buy(lotstart, symbolArray[symbolSub], askSub, 0, 0, "hell");//hell[symbolToTrade].TotalSize()
trade.Sell(lotstart, symbolArray[symbolToTrade], bid, 0, 0, "paradise");//paradise[symbolToTrade].TotalSize()
}
hell[symbolToTrade].Updater(symbolArray[symbolToTrade],"hell",ArraySize(hell[symbolToTrade].ID));
paradise[symbolSub].Updater(symbolArray[symbolSub],"paradise",ArraySize(paradise[symbolSub].ID));
hell[symbolSub].Updater(symbolArray[symbolSub],"hell",ArraySize(hell[symbolSub].ID));
paradise[symbolToTrade].Updater(symbolArray[symbolToTrade],"paradise",ArraySize(paradise[symbolToTrade].ID));
Print(" pairCorr ", pairCorr, " tickCorr ", tickCorr);
}
//add // && pairCorr > pairStrength && tickCorr > tickStrength
if(signal > corrStrength && open && ArraySize(hell[symbolToTrade].ID) > 0 && hellGlob < 0 && ask < hell[symbolToTrade].Border())// && bidSub > paradise[symbolSub].Border())
{
double volCorr = 1;//paraGlob > hellGlob ? (1 + MathAbs(MathAbs(paraGlob)/MathAbs(hellGlob)-1)) : (1 + MathAbs(MathAbs(hellGlob)/MathAbs(paraGlob)-1));
if(bidSub > paradise[symbolSub].Border())
{
trade.Sell((paraGlob > hellGlob ? NormalizeDouble(paradise[symbolSub].TotalSize()*volCorr,2) : paradise[symbolSub].TotalSize()), symbolArray[symbolSub], bidSub, 0, 0, "paradise");//paradise[symbolToTrade].TotalSize()
paradise[symbolSub].Updater(symbolArray[symbolSub],"paradise",ArraySize(paradise[symbolSub].ID));
Print("add Hell add");
}
if(maxHell <= maxPara*2)
{
trade.Buy((paraGlob > hellGlob ? hell[symbolToTrade].TotalSize() : NormalizeDouble(hell[symbolToTrade].TotalSize()*volCorr,2)), symbolArray[symbolToTrade], ask, 0, 0, "hell");//hell[symbolToTrade].TotalSize()
hell[symbolToTrade].Updater(symbolArray[symbolToTrade],"hell",ArraySize(hell[symbolToTrade].ID));
Print("hell add");
}
if(maxHell >= maxPara*2)
{
trade.Sell((paraGlob > hellGlob ? NormalizeDouble(paradise[symbolSub].TotalSize()*volCorr,2) : paradise[symbolSub].TotalSize()), symbolArray[symbolSub], bidSub, 0, 0, "paradise");//paradise[symbolToTrade].TotalSize()
paradise[symbolSub].Updater(symbolArray[symbolSub],"paradise",ArraySize(paradise[symbolSub].ID));
Print("Dobros Lock hell");
}
}
// && pairCorr > pairStrength && tickCorr > tickStrength
if(signal < -corrStrength && open && ArraySize(paradise[symbolToTrade].ID) > 0 && paraGlob < 0 && bid > paradise[symbolToTrade].Border())// && askSub < hell[symbolSub].Border())
{
double volCorr = 1;//hellGlob > paraGlob ? (1 + MathAbs(MathAbs(paraGlob)/MathAbs(hellGlob)-1)) : (1 + MathAbs(MathAbs(hellGlob)/MathAbs(paraGlob)-1));
if(askSub < hell[symbolSub].Border())
{
trade.Buy((hellGlob > paraGlob ? NormalizeDouble(hell[symbolSub].TotalSize()*volCorr,2) : hell[symbolSub].TotalSize()), symbolArray[symbolSub], askSub, 0, 0, "hell");//hell[symbolToTrade].TotalSize()
hell[symbolSub].Updater(symbolArray[symbolSub],"hell",ArraySize(hell[symbolSub].ID));
Print("add Para add");
}
if(maxPara <= maxHell*2)
{
trade.Sell((hellGlob > paraGlob ? paradise[symbolToTrade].TotalSize() : NormalizeDouble(paradise[symbolToTrade].TotalSize()*volCorr,2)), symbolArray[symbolToTrade], bid, 0, 0, "paradise");//paradise[symbolToTrade].TotalSize()
paradise[symbolToTrade].Updater(symbolArray[symbolToTrade],"paradise",ArraySize(paradise[symbolToTrade].ID));
Print("para add");
}
if(maxPara >= maxHell*2)
{
trade.Buy((hellGlob > paraGlob ? NormalizeDouble(hell[symbolSub].TotalSize()*volCorr,2) : hell[symbolSub].TotalSize()), symbolArray[symbolSub], askSub, 0, 0, "hell");//hell[symbolToTrade].TotalSize()
hell[symbolSub].Updater(symbolArray[symbolSub],"hell",ArraySize(hell[symbolSub].ID));
Print("Dobros Lock hell");
}
}
//END OF POSITION GENERATOR
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
if(PositionsTotal() == 0)
{
hell[symbolToTrade].Updater(symbolArray[symbolToTrade],"hell",ArraySize(hell[symbolToTrade].ID));
paradise[symbolToTrade].Updater(symbolArray[symbolToTrade],"paradise",ArraySize(paradise[symbolToTrade].ID));
}
//+------------------------------------------------------------------+
//| RADIO GAGA |
//+------------------------------------------------------------------+
if(radio && ((account.Equity() > balance*(1 + gagaPercent/100))))// || (pairCorr < pairWeak && PositionsTotal() > 1))) // || (account.Equity() > account.Balance() && ArraySize(hell[symbolToTrade].ID) > 0 && ArraySize(paradise[symbolToTrade].ID) > 0)))
// && ((ArraySize(paradise[symbolToTrade].ID) == 0 && ArraySize(hell[symbolToTrade].ID) > 1) || (ArraySize(paradise[symbolToTrade].ID) > 1 && ArraySize(hell[symbolToTrade].ID) == 0))
{
//Base Gaga
for(int i=PositionsTotal() ; i>=0; i--)
{
ulong marker = PositionGetTicket(i);
PositionSelectByTicket(marker);
{
trade.PositionClose(marker);
}
}
//hold = 0;
Print("Close ALL");
}
symbolToTrade = NULL;
//dve skobki } /n }
}
}
}//конец OnTick()
//+------------------------------------------------------------------+