//+------------------------------------------------------------------+ //| Fuzzy logic for fuzzy algotraders.mq5 | //| Copyright 2017, Dmitrievskiy Max. | //| https://www.mql5.com/ru/users/dmitrievsky | //+------------------------------------------------------------------+ #property copyright "Copyright 2017, Dmitrievskiy Max." #property link "https://www.mql5.com/ru/users/dmitrievsky" #property version "1.00" #include #include #include CMamdaniFuzzySystem *OurFuzzy=new CMamdaniFuzzySystem(); CFuzzyVariable *firstInput=new CFuzzyVariable("rsi1",0.0,1.0); CFuzzyVariable *secondInput=new CFuzzyVariable("rsi2",0.0,1.0); CFuzzyVariable *thirdInput=new CFuzzyVariable("rsi3",0.0,1.0); CFuzzyVariable *fuzzyOut=new CFuzzyVariable("out",0.0,1.0); CDictionary_Obj_Double *firstTerm=new CDictionary_Obj_Double; CDictionary_Obj_Double *secondTerm=new CDictionary_Obj_Double; CDictionary_Obj_Double *thirdTerm=new CDictionary_Obj_Double; CDictionary_Obj_Double *Output; CMamdaniFuzzyRule *rule1, *rule2, *rule3, *rule4, *rule5, *rule6, *rule7, *rule8, *rule9, *rule10, *rule11, *rule12; CList *Inputs=new CList; int hnd1, hnd2, hnd3; double arr1[], arr2[], arr3[]; input string Fuzzy_Setings; //Fuzzy optimization settings input double Gsigma = 0.5; //sigma From 0.05 to 0.5 with 0.05 step input double Gposition=0.5; //position From 0.0 to 1.0 with 0.1 step input double MinNeutralSignal=0.4; //MinNeutralSignal from 0.3 to 0.5 with 0.1 step input double MaxNeutralSignal=0.6; //MaxNeutralSignal from 0.5 to 0.7 with 0.1 step input string Lotsettings; //Trade settings input double MaximumRisk=0.01; input double CustomLot=0; input int OrderMagic=666; double lots; static datetime last_time=0; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- Inputs.FreeMode(false); hnd1 = iRSI(_Symbol,0,9,PRICE_CLOSE); hnd2 = iRSI(_Symbol,0,14,PRICE_CLOSE); hnd3 = iRSI(_Symbol,0,21,PRICE_CLOSE); firstInput.Terms().Add(new CFuzzyTerm("buy", new CZ_ShapedMembershipFunction(0.0,0.6))); firstInput.Terms().Add(new CFuzzyTerm("neutral", new CNormalMembershipFunction(0.5, 0.2))); firstInput.Terms().Add(new CFuzzyTerm("sell", new CS_ShapedMembershipFunction(0.4,1.0))); OurFuzzy.Input().Add(firstInput); secondInput.Terms().Add(new CFuzzyTerm("buy", new CZ_ShapedMembershipFunction(0.0,0.6))); secondInput.Terms().Add(new CFuzzyTerm("neutral", new CNormalMembershipFunction(0.5, 0.2))); secondInput.Terms().Add(new CFuzzyTerm("sell", new CS_ShapedMembershipFunction(0.4,1.0))); OurFuzzy.Input().Add(secondInput); thirdInput.Terms().Add(new CFuzzyTerm("buy", new CZ_ShapedMembershipFunction(0.0,0.6))); thirdInput.Terms().Add(new CFuzzyTerm("neutral", new CNormalMembershipFunction(0.5, 0.2))); thirdInput.Terms().Add(new CFuzzyTerm("sell", new CS_ShapedMembershipFunction(0.4,1.0))); OurFuzzy.Input().Add(thirdInput); fuzzyOut.Terms().Add(new CFuzzyTerm("buy", new CZ_ShapedMembershipFunction(0.0,0.6))); fuzzyOut.Terms().Add(new CFuzzyTerm("neutral", new CNormalMembershipFunction(Gposition, Gsigma))); fuzzyOut.Terms().Add(new CFuzzyTerm("sell", new CS_ShapedMembershipFunction(0.4,1.0))); OurFuzzy.Output().Add(fuzzyOut); rule1 = OurFuzzy.ParseRule("if (rsi1 is buy) and (rsi2 is buy) and (rsi3 is buy) then (out is buy)"); rule2 = OurFuzzy.ParseRule("if (rsi1 is sell) and (rsi2 is sell) and (rsi3 is sell) then (out is sell)"); rule3 = OurFuzzy.ParseRule("if (rsi1 is neutral) and (rsi2 is neutral) and (rsi3 is neutral) then (out is neutral)"); rule4 = OurFuzzy.ParseRule("if (rsi1 is buy) and (rsi2 is sell) and (rsi3 is buy) then (out is neutral)"); rule5 = OurFuzzy.ParseRule("if (rsi1 is sell) and (rsi2 is sell) and (rsi3 is buy) then (out is neutral)"); rule6 = OurFuzzy.ParseRule("if (rsi1 is buy) and (rsi2 is buy) and (rsi3 is sell) then (out is neutral)"); rule7 = OurFuzzy.ParseRule("if (rsi1 is buy) and (rsi2 is buy) and (rsi3 is neutral) then (out is buy)"); rule8 = OurFuzzy.ParseRule("if (rsi1 is sell) and (rsi2 is sell) and (rsi3 is neutral) then (out is sell)"); rule9 = OurFuzzy.ParseRule("if (rsi1 is buy) and (rsi2 is neutral) and (rsi3 is buy) then (out is buy)"); rule10 = OurFuzzy.ParseRule("if (rsi1 is sell) and (rsi2 is neutral) and (rsi3 is sell) then (out is sell)"); rule11 = OurFuzzy.ParseRule("if (rsi1 is neutral) and (rsi2 is buy) and (rsi3 is buy) then (out is buy)"); rule12 = OurFuzzy.ParseRule("if (rsi1 is neutral) and (rsi2 is sell) and (rsi3 is sell) then (out is sell)"); OurFuzzy.Rules().Add(rule1); OurFuzzy.Rules().Add(rule2); OurFuzzy.Rules().Add(rule3); OurFuzzy.Rules().Add(rule4); OurFuzzy.Rules().Add(rule5); OurFuzzy.Rules().Add(rule6); OurFuzzy.Rules().Add(rule7); OurFuzzy.Rules().Add(rule8); OurFuzzy.Rules().Add(rule9); OurFuzzy.Rules().Add(rule10); OurFuzzy.Rules().Add(rule11); OurFuzzy.Rules().Add(rule12); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- Inputs.FreeMode(true); delete Inputs; delete OurFuzzy; ChartRedraw(); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- if(!isNewBar()) { return; } double TradeSignal=CalculateMamdani(); if(CountOrders(0)!=0 || CountOrders(1)!=0) { for(int b=OrdersTotal()-1; b>=0; b--) { if(OrderSelect(b,SELECT_BY_POS)==true) { if(OrderSymbol()==_Symbol && OrderMagicNumber()==OrderMagic) { if(OrderType()==OP_BUY && TradeSignal>=MinNeutralSignal) { if(OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),0,Red)) { if(TradeSignal>MaxNeutralSignal) { lots = LotsOptimized(); if(OrderSend(Symbol(),OP_SELL,lots,SymbolInfoDouble(_Symbol,SYMBOL_BID),0,0,0,NULL,OrderMagic,Red)){ }; } } } if(OrderType()==OP_SELL && TradeSignal<=MaxNeutralSignal) { if(OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),0,Red)) { if(TradeSignalMaxNeutralSignal && CheckMoneyForTrade(_Symbol,lots,ORDER_TYPE_SELL)) { if(OrderSend(Symbol(),OP_SELL,lots,SymbolInfoDouble(_Symbol,SYMBOL_BID),0,0,0,NULL,OrderMagic,Red)){ }; } return; } //+------------------------------------------------------------------+ double CalculateMamdani() { CopyBuffer(hnd1,0,0,1,arr1); NormalizeArrays(arr1); CopyBuffer(hnd2,0,0,1,arr2); NormalizeArrays(arr2); CopyBuffer(hnd3,0,0,1,arr3); NormalizeArrays(arr3); firstTerm.SetAll(firstInput,arr1[0]); secondTerm.SetAll(secondInput,arr2[0]); thirdTerm.SetAll(thirdInput,arr2[0]); Inputs.Clear(); Inputs.Add(firstTerm); Inputs.Add(secondTerm); Inputs.Add(thirdTerm); CList *FuzzResult=OurFuzzy.Calculate(Inputs); Output=FuzzResult.GetNodeAtIndex(0); double res = Output.Value(); delete FuzzResult; return(res); } void NormalizeArrays(double &a[]) { double d1=0; double d2=1.0; double x_min=0.0; double x_max=100; for(int i=0;i0.0000001) { lot = ratio*volume_step; } if(lotSymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX)) lot=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX); return(lot); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool isNewBar() { datetime lastbar_time=datetime(SeriesInfoInteger(Symbol(),_Period,SERIES_LASTBAR_DATE)); if(last_time==0) { last_time=lastbar_time; return(false); } if(last_time!=lastbar_time) { last_time=lastbar_time; return(true); } return(false); } //+------------------------------------------------------------------+ bool CheckMoneyForTrade(string symb,double lot,ENUM_ORDER_TYPE type) { //--- Getting the opening price MqlTick mqltick; SymbolInfoTick(symb,mqltick); double price=mqltick.ask; if(type==ORDER_TYPE_SELL) price=mqltick.bid; //--- values of the required and free margin double margin,free_margin=AccountInfoDouble(ACCOUNT_MARGIN_FREE); //--- call of the checking function if(!OrderCalcMargin(type,symb,lots,price,margin)) { //--- something went wrong, report and return false Print("Error in ",__FUNCTION__," code=",GetLastError()); return(false); } //--- if there are insufficient funds to perform the operation if(margin>free_margin) { //--- report the error and return false Print("Not enough money for ",EnumToString(type)," ",lots," ",symb," Error code=",GetLastError()); return(false); } //--- checking successful return(true); }