oslib/tst/fuzzy_3795/Fuzzy_logic_for_fuzzy_algotraders.mq5
super.admin 07f69c4478 convert
2025-05-30 16:15:18 +02:00

306 lines
No EOL
23 KiB
MQL5

//+------------------------------------------------------------------+
//| 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 <Math\Fuzzy\MamdaniFuzzySystem.mqh>
#include <Trade\AccountInfo.mqh>
#include <MT4Orders.mqh>
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(TradeSignal<MinNeutralSignal)
{
lots = LotsOptimized();
if(OrderSend(Symbol(),OP_BUY,lots,SymbolInfoDouble(_Symbol,SYMBOL_ASK),0,0,0,NULL,OrderMagic,Green)){
};
}
}
}
}
}
}
return;
}
lots = LotsOptimized();
if(TradeSignal<MinNeutralSignal && CheckMoneyForTrade(_Symbol,lots,ORDER_TYPE_BUY))
{
if(OrderSend(Symbol(),OP_BUY,lots,SymbolInfoDouble(_Symbol,SYMBOL_ASK),0,0,0,NULL,OrderMagic,Green)){
};
}
else if(TradeSignal>MaxNeutralSignal && 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;i<ArraySize(a);i++)
{
a[i]=(((a[i]-x_min)*(d2-d1))/(x_max-x_min))+d1;
}
}
int CountOrders(int a)
{
int result=0;
for(int k=0; k<OrdersTotal(); k++)
{
if(OrderSelect(k,SELECT_BY_POS,MODE_TRADES)==true)
{
if(OrderType()==a && OrderMagicNumber()==OrderMagic && OrderSymbol()==_Symbol)
{result++;}
}
}
return(result);
}
double LotsOptimized()
{
CAccountInfo myaccount; SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_STEP);
double lot;
lot=NormalizeDouble(myaccount.FreeMargin()*MaximumRisk/1000.0,2);
if(CustomLot!=0.0) lot=CustomLot;
double volume_step=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_STEP);
int ratio=(int)MathRound(lot/volume_step);
if(MathAbs(ratio*volume_step-lot)>0.0000001)
{
lot = ratio*volume_step;
}
if(lot<SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MIN)) lot=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MIN);
if(lot>SymbolInfoDouble(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);
}