389 lines
38 KiB
MQL5
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()
|
|
|
|
//+------------------------------------------------------------------+
|