SwapFinder_script





//+------------------------------------------------------------------+
//|                                            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