//+------------------------------------------------------------------+ //| Includes | //+------------------------------------------------------------------+ //test #include #include #include #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 0) { for(int i=0; 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() //+------------------------------------------------------------------+