//+------------------------------------------------------------------+ //| SwapFinder_script.mq4 | //| Copyright © 2006, MetaQuotes Software Corp. | //| http://www.metaquotes.net | //+------------------------------------------------------------------+ #property copyright "Bogdan Caramalac" #property link "mailto:fxeconomist@yahoo.com" extern int MarginUsage=90; extern int MaxCurrenciesUsed=3; extern bool JustTesting=False; extern int Slippage=3; extern bool ShowNegatives=False; #include <bclib.mqh> #include <WinUser32.mqh> //however, this will slow down the process bool FatalError=false; int TickDenominator=1; string Appendix=""; int SwapType=-1; //************************************************************************************** bool IsConfigValid(string BinConfig,int Permutation,int &Loaded,string &contracts[16],int &ops[16]) { bool res=false; int i; int perm[16]; bool cex1,cex2; int Asc1=49; string ctest1,ctest2; string LoadedCrrcies[16]; string permcrrcies[16]; for (i=0;i<16;i++) { perm[i]=0; permcrrcies[i]=""; LoadedCrrcies[i]=""; ops[i]=0; contracts[i]=""; } Loaded=0; for (i=0;i<StringLen(BinConfig);i++) { if (StringGetChar(BinConfig,i)==Asc1) { LoadedCrrcies[Loaded]=UsableCurrencies[i]; Loaded=Loaded+1; } } if (Loaded<3) return(res); GenPermutation(Permutation,Loaded,perm); for (i=0;i<Loaded;i++) { permcrrcies[i]=LoadedCrrcies[perm[i]-1]; } res=True; for (i=0;i<Loaded;i++) { if (i==Loaded-1) { //supposing continuous sell...from the first currency, to the first again //if a contract does not exist, it will be reversed and bought ctest1=StringConcatenate(permcrrcies[i],permcrrcies[0],Appendix); ctest2=StringConcatenate(permcrrcies[0],permcrrcies[i],Appendix); cex1=ContractIsTraded(ctest1); cex2=ContractIsTraded(ctest2); if (cex1==False&&cex2==False) { res=false; return(res); } if (cex1==True) { ops[i]=OP_SELL; contracts[i]=ctest1; } else { ops[i]=OP_BUY; contracts[i]=ctest2; } } else { //supposing continuous sell...from the first currency, to the first again //if a contract does not exist, it will be reversed and bought ctest1=StringConcatenate(permcrrcies[i],permcrrcies[i+1],Appendix); ctest2=StringConcatenate(permcrrcies[i+1],permcrrcies[i],Appendix); cex1=ContractIsTraded(ctest1); cex2=ContractIsTraded(ctest2); if (cex1==False&&cex2==False) { res=false; return(res); } if (cex1==True) { ops[i]=OP_SELL; contracts[i]=ctest1; } else { ops[i]=OP_BUY; contracts[i]=ctest2; } } }//for (i=0;i<Loaded;i++) return(res); } void EstablishSwaps(int CrrNo,string contracts[],int ops[],double volumes[],double &usage[],double &TotalUsed,double &Swaps[],double &Interests[],double &NormalROA[],double &WeightedROA[],double &ROA, double &ROE, bool ShowSwaps) { int i; bool brokerfound=False; double m_tick,m_lotsize; int mode; string crr1; TotalUsed=0; for (i=0;i<CrrNo;i++) { crr1=StringSubstr(contracts[i],0,3); usage[i]=volumes[i]*GetCurrency(crr1,AccountCurrency(),Appendix); TotalUsed=TotalUsed+usage[i]; } for (i=0;i<CrrNo;i++) { crr1=StringSubstr(contracts[i],0,3); if (ops[i]==OP_BUY) { Swaps[i]=MarketInfo(contracts[i],MODE_SWAPLONG); mode=MODE_SWAPLONG; } else { Swaps[i]=MarketInfo(contracts[i],MODE_SWAPSHORT); mode=MODE_SWAPSHORT; } Interests[i]=Swap2Interest_Volume(volumes[i],mode,StringSubstr(contracts[i],0,6),Appendix); NormalROA[i]=((Interests[i]/usage[i])*100)*365; WeightedROA[i]=NormalROA[i]*usage[i]/TotalUsed; ROA=ROA+WeightedROA[i]; } ROE=ROA*TotalUsed/AccountEquity(); } void EstablishRing(int CrrNo,string contracts[],int ops[],double &volumes[],double &usage[],double &TotalUsed, double &Swaps[],double &Interests[],double &NormalROA[],double &WeightedROA[],double &ROA, double &ROE, double &FXResult, double &FinalROE, bool ShowSwaps) { string ctest1; int ms; bool cex1; int i; int available; if (JustTesting==false) available=Truncate(AccountFreeMargin()*AccountLeverage()*(MarginUsage/100.00)); else available=Truncate(AccountEquity()*AccountLeverage()*(MarginUsage/100.00)); available=Truncate(AccountBalance()*AccountLeverage()*(MarginUsage/100.00)); //WriteLn("Available = "+DoubleToStr(available,0)); int q=available/CrrNo; string crr1,crr2; double got,units; double mk,Interest; string rev; string ResultCrrcy; int operation; for (i=0;i<CrrNo;i++) { crr1=StringSubstr(contracts[i],0,3); crr2=StringSubstr(contracts[i],3,3); if (i==0) { volumes[i]=0; mk=GetCurrency(AccountCurrency(),crr1,Appendix); units=q*mk; volumes[i]=UnitsToLots(units,contracts[i])*MarketInfo(contracts[i],MODE_LOTSIZE); rev=""; if (ops[i]==OP_SELL) { got=volumes[i]*MarketInfo(contracts[i],MODE_BID); ResultCrrcy=crr2; } else { got=volumes[i]; ResultCrrcy=crr1; } } else { if (ResultCrrcy==crr1)//we have the 1st currency at entry, we have a SHORT { units=got; volumes[i]=UnitsToLots(units,contracts[i])*MarketInfo(contracts[i],MODE_LOTSIZE); rev=""; ResultCrrcy=crr2; mk=MarketInfo(contracts[i],MODE_BID); got=mk*volumes[i]; } else//we have a LONG { mk=MarketInfo(contracts[i],MODE_ASK); units=got*(1/mk); rev="reversed"; volumes[i]=UnitsToLots(units,contracts[i])*MarketInfo(contracts[i],MODE_LOTSIZE); ResultCrrcy=crr1; got=volumes[i]; } }//else if (i==0) //usage[i]=volumes[i]*GetCurrency(crr1,AccountCurrency()); //TotalUsed=TotalUsed+usage[i]; //WriteLn(StringConcatenate("Got ",DoubleToStr(got,4)," in ",ResultCrrcy," by applying rate ",DoubleToStr(mk,4)," of ",contracts[i]," ",rev)); //WriteLn(StringConcatenate("---------", OrderType2Str(ops[i])," ",DoubleToStr(volumes[i],0)," ",contracts[i] ) ); }//for (i=0;i<CrrNo;i++) ROA=0; ROE=0; FXResult=0; for (i=0;i<CrrNo;i++) { FXResult=FXResult-MarketInfo(contracts[i],MODE_SPREAD)*(MarketInfo(contracts[i],MODE_TICKVALUE)/TickDenominator)*volumes[i]/10000; } FXResult=(FXResult/AccountEquity())*100; EstablishSwaps(CrrNo,contracts,ops,volumes,usage,TotalUsed,Swaps,Interests,NormalROA,WeightedROA,ROA,ROE,ShowSwaps); FinalROE=ROE+FXResult; return; } void GetBestRing(int maxcrrcies, int &bestconfig, int &permutation, string lookfor,string lookops) { int icomb,maxperm,iperm; double Usage[16]; int maxim; string image; string Contracts[16]; int Ops[16]; string combimg,permimg; double Volumes[16]; bool valid; double ROA,ROE; double Swaps[16]; double NormalROA[16]; double WeightedROA[16]; double Interests[16]; int crrcies,iimg; double TotalSwap,TotalUsed; double FXResult,FinalROE; int lookcomb=-1; int lookperm=-1; int best=-1; permutation=-1; double maximdbl=Truncate(MathPow(2,CurrenciesNo))-1; double bestswap=-99999999; double lookswap=-99999999; bool look=false; string lookfor0,lookfor1,lookfor2; int lookops0,lookops1,lookops2; if (StringLen(lookfor)!=0) { lookfor0=Upper(ReturnNthWord(lookfor,1)); if (StringElement(Upper(lookops),0)=="B") lookops0=OP_BUY; else lookops0=OP_SELL; lookfor1=Upper(ReturnNthWord(lookfor,2)); if (StringElement(Upper(lookops),1)=="B") lookops1=OP_BUY; else lookops1=OP_SELL; lookfor2=Upper(ReturnNthWord(lookfor,3)); if (StringElement(Upper(lookops),2)=="B") lookops2=OP_BUY; else lookops2=OP_SELL; look=True; //ClearSplash(); //SplashLn( lookfor0+" "+lookfor1+" "+lookfor2+" "+OrderType2Str(lookops0)+" "+OrderType2Str(lookops1)+" "+OrderType2Str(lookops2) ); //SplashScreen(); } maxim=MathRound(maximdbl); WriteLn(StringConcatenate("Maximal combination: ",DoubleToStr(maxim,0))); WriteLn(""); int fhandle=FileOpen("ringlist.txt",FILE_WRITE); for (icomb=maxim;icomb>=0;icomb--) { image=Padl(ConvertTo(2,icomb),CurrenciesNo,"0"); crrcies=Occurs("1",image); valid=false; if (crrcies>=3&&crrcies<=maxcrrcies) { maxperm=Factorial(crrcies)-1; combimg=""; for (iimg=0;iimg<CurrenciesNo;iimg++) { if (StringElement(image,iimg)=="1") combimg=StringConcatenate(combimg,UsableCurrencies[iimg]," "); } WriteLn(StringConcatenate("Studying ",combimg," having ",DoubleToStr(maxperm+1,0)," permutations")); for (iperm=0;iperm<=maxperm;iperm++) { ROA=-1; ROE=-1; valid=IsConfigValid(image,iperm,crrcies,Contracts,Ops); if (valid==True) { EstablishRing(crrcies,Contracts,Ops,Volumes,Usage,TotalUsed,Swaps,Interests,NormalROA,WeightedROA,ROA,ROE,FXResult,FinalROE,False); if (FatalError==true) { FileClose(fhandle); return; } if (valid==false) continue; if ((FinalROE>0)||(FinalROE<0&&ShowNegatives==True)) { WriteLn(StringConcatenate(" Found ring with ROA=",DoubleToStr(ROA,4),"% ROE=",DoubleToStr(ROE,4),"% FinalROE=",DoubleToStr(FinalROE,4),"%")); if (FinalROE>0) FileWrite(fhandle,StringConcatenate(Contracts[0]," ",Contracts[1]," ",Contracts[2]," ",StringElement(OrderType2Str(Ops[0]),0), StringElement(OrderType2Str(Ops[1]),0),StringElement(OrderType2Str(Ops[2]),0)," ROA=",DoubleToStr(ROA,4),"% ROE=",DoubleToStr(ROE,4),"% FinalROE=",DoubleToStr(FinalROE,4),"%" )); } if (ROA>bestswap&&ROA>=0) { best=icomb; permutation=iperm; bestswap=ROA; }//if (TotalSwap>=bestswap&&TotalSwap>=0) if (look==True) { if (Contracts[0]==lookfor0&&Contracts[1]==lookfor1&&Contracts[2]==lookfor2&&Ops[0]==lookops0&&Ops[1]==lookops1&&Ops[2]==lookops2) { lookcomb=icomb; lookperm=iperm; lookswap=ROA; } } }//if (valid==True); }//for (iperm=0;iperm<=maxperm;iperm++) }//if (crrcies>=3) }//for (icomb=0;icomb<=maxim;icomb++) Say(2,"Done"); if (lookperm!=-1) { best=lookcomb; permutation=lookperm; bestswap=lookswap; } WriteLn("Best has been chosen combination "+DoubleToStr(best,0)); bestconfig=best; FileClose(fhandle); return; } int GetMaxMagic() { int maxmagic=0; int ntrades=OrdersTotal(); int i; int mhere=0; if (ntrades!=0) { for (i=0;i<ntrades;i++) { OrderSelect(i,SELECT_BY_POS,MODE_TRADES); mhere=OrderMagicNumber(); if (mhere>maxmagic) maxmagic=mhere; } } return(mhere); } void TradeRing(int CrrNo,int Ops[],string Contracts[],double Volumes[],int Magic) { ClearSplash(); int i,Gle; double price; string ErrType,ErrText,ErrExplanation; for (i=0;i<CrrNo;i++) { if (Ops[i]==OP_BUY) price=MarketInfo(Contracts[i],MODE_ASK); else price=MarketInfo(Contracts[i],MODE_BID); SplashLn("Trying with "+Contracts[i]+" "+DoubleToStr( NormalizeDouble(Volumes[i]/1000*0.01,2) , 2) ) ; OrderSend(Contracts[i],Ops[i],NormalizeDouble(Volumes[i]/1000*0.01,2),price,Slippage,0,0,"RING "+DoubleToStr(Magic,0),Magic,0,Blue); Gle=GetLastError(); if (Gle!=0) { TranslateError(Gle,ErrType,ErrText,ErrExplanation); SplashLn(ErrType+CRLF()+ErrText+CRLF()+ErrExplanation); SplashScreen(); } } } void AnalyseRing(int nRing) { int crrcies=0; double Usage[16]; string Contracts[16]; int Ops[16]; double Volumes[16]; double ROA,ROE; double Swaps[16]; double NormalROA[16]; double WeightedROA[16]; double Interests[16]; double TotalUsed; int ntrades=OrdersTotal(); int i,mhere; double op; op=0; if (ntrades!=0) { for (i=0;i<ntrades;i++) { OrderSelect(i,SELECT_BY_POS,MODE_TRADES); mhere=OrderMagicNumber(); if (mhere==nRing) { Contracts[crrcies]=StringSubstr(OrderSymbol(),0,6); Ops[crrcies]=OrderType(); Volumes[crrcies]=OrderLots()*MarketInfo(OrderSymbol(),MODE_LOTSIZE); //WriteLn(Contracts[crrcies]+" "+DoubleToStr(Ops[crrcies],0)+" "+DoubleToStr(Volumes[crrcies],2)); crrcies=crrcies+1; op=op+OrderProfit(); } } if (crrcies!=0) { EstablishSwaps(crrcies,Contracts,Ops,Volumes,Usage,TotalUsed,Swaps,Interests,NormalROA,WeightedROA,ROA,ROE,False); DisplayRing("Currently traded ring ( having magic "+Alltrim(DoubleToStr(mhere,0))+" )",(op/AccountEquity())*100,crrcies,Contracts,Ops,Volumes,Usage,TotalUsed,Swaps,Interests,NormalROA,WeightedROA,ROA,ROE); } } return; } string Alligned(int optype) { if (optype==OP_BUY) return("Buy"); else return("Sell "); } void DisplayRing(string title,double op,int crrcies,string Contracts[],int Ops[],double &Volumes[],double &Usage[],double &TotalUsed,double &Swaps[],double &Interests[],double &NormalROA[],double &WeightedROA[],double &ROA, double &ROE) { int iimg; ClearSplash(); SplashLn(title); SplashLn(""); SplashLn("Usage("+AccountCurrency()+") % Op. Volume Lots Contract Swap Interest NormalROA WeightedROA"); SplashLn(""); for (iimg=0;iimg<crrcies;iimg++) SplashLn( StringConcatenate( Padl(DoubleToStr(Usage[iimg],2),10," ")," ", Padl(DoubleToStr(Usage[iimg]/TotalUsed*100,4),8," ")," ", Alligned(Ops[iimg])," ", Padl(DoubleToStr(Volumes[iimg],2),10," ")," ", Padl(DoubleToStr(Volumes[iimg]/MarketInfo(Contracts[iimg],MODE_LOTSIZE),2),6," ")," ", Lower(Contracts[iimg])," ", Padl(DoubleToStr(Swaps[iimg],4),10," ")," ", Padl(DoubleToStr(Interests[iimg],4),10," ")," ", Padl(DoubleToStr(NormalROA[iimg],4),10," ")," ", Padl(DoubleToStr(WeightedROA[iimg],4),10," ") )); SplashLn(""); SplashLn(DoubleToStr(TotalUsed,2)); SplashLn(""); SplashLn(" ROA = "+DoubleToStr(ROA,4)+"%"); SplashLn(" ROE = "+DoubleToStr(ROE,4)+"%"); if (op!=0) { SplashLn(""); SplashLn("Forex result = "+DoubleToStr(op,4)+"%"); SplashLn(""); SplashLn("Final ROE = "+DoubleToStr(ROE+op,4)+"%"); } SplashScreen(); } void ScanRings(int maxcrrcies) { string Contracts[16]; int Ops[16]; double Volumes[16]; double Usage[16]; string image; double ROA,ROE; double Swaps[16]; double NormalROA[16]; double WeightedROA[16]; double Interests[16]; double FXResult,FinalROE; bool valid; int mb; int gmm,icrt; double TotalUsed; int bestconfig,bestperm,crrcies,iimg,ms; GetBestRing(maxcrrcies,bestconfig,bestperm,"",""); if (FatalError==true) return; if (bestconfig!=-1) { image=Padl(ConvertTo(2,bestconfig),CurrenciesNo,"0"); valid=IsConfigValid(image,bestperm,crrcies,Contracts,Ops); EstablishRing(crrcies,Contracts,Ops,Volumes,Usage,TotalUsed,Swaps,Interests,NormalROA,WeightedROA,ROA,ROE,FXResult,FinalROE,True); if (FinalROE>0) { ClearSplash(); DisplayRing("Best ring found ",FXResult,crrcies,Contracts,Ops,Volumes,Usage,TotalUsed,Swaps,Interests,NormalROA,WeightedROA,ROA,ROE); SplashLn("Combination = "+DoubleToStr(bestconfig,0) ); SplashLn("Permutation ="+DoubleToStr(bestperm,0) ); } else { ClearSplash(); SplashLn("Sorry, nothing found!"); SplashScreen(); ClearSplash(); } } else { ClearSplash(); SplashLn("Sorry, nothing found!"); SplashScreen(); ClearSplash(); } if (JustTesting==True) //era (OrdersTotal()!=0||JustTesting==True) mb=SplashScreen(); else { if (bestconfig!=-1) { SplashLn(""); SplashLn("Trade ring ?"); mb=SplashScreen(MB_YESNO); if (mb==IDYES) { TradeRing(crrcies,Ops,Contracts,Volumes,GetMaxMagic()+1); } } } ClearSplash(); gmm=GetMaxMagic(); if (gmm!=0) { for (icrt=0;icrt<=gmm;icrt++) AnalyseRing(icrt); } } int init() { Appendix=GetSymbolsAppendix(); TickDenominator=GetTickDenominator(Appendix); GetCurrenciesAndPairs(Appendix); SetTextParameters("Courier New",10); ClearText(); if (FatalError==true) return; for (int i=0;i<CurrenciesNo;i++) Write(UsableCurrencies[i]+" "); WriteLn(""); WriteLn(""); SetTextFirstScroll(4); if ((JustTesting==false)&&(IsTradeAllowed()==false)) { WriteLn("Script is set to trade, yet not allowed from setup window at startup!"); FatalError=true; } if (FatalError==true) return(1); return(0); } //+------------------------------------------------------------------+ //| script program start function | //+------------------------------------------------------------------+ int start() { int gm=GetMaxMagic(); if (gm!=0) { for (int i=1;i<=gm;i++) { AnalyseRing(i); } } if (MaxCurrenciesUsed==0) ScanRings(CurrenciesNo); else ScanRings(MaxCurrenciesUsed); return(0); } //+------------------------------------------------------------------+
Sample
Analysis
Market Information Used:
Indicator Curves created:
Indicators Used:
Custom Indicators Used:
Order Management characteristics:
Checks for the total of open orders
It automatically opens orders when conditions are reached
Other Features:
Uses files from the file system
It writes information to file