//+------------------------------------------------------------------+
//| COT.mq4 |
//| |
//| |
//+------------------------------------------------------------------+
/*
COT index formula:
The COT index is stochastic oscillator of the Net.
Net = Positions long - Positions short.
WILLCO index formula:
The WILLCO index is stochastic oscillator of the %Net.
%Net = 100%*(Positions long - Positions short) / OI.
The OI is open interest.
OI index formula:
The OI index is stochastic oscillator of the OI.
Movement index formula:
Movement index = COT(t) - COT(t+n).
The n is the period of the Movement index.
The t is an interval.
The COT(t) is current value of the COT index.
The COT(t+n) is value of the COT index n weeks ago.
Spread movement index formula:
Spread movement index = Movement index - OI Movement index.
Movement index = COT(t) - COT(t+n).
OI Movement index = OI index(t) - OI index(t+n).
The n is the period of the Spread movement index.
The t is an interval.
The COT(t) is current value of the COT index.
The OI index(t) is current value of the OI index.
The COT(t+n) is value of the COT index n weeks ago.
The OI index(t+n) is value of the OI index n weeks ago.
How to begin to work?
The indicator COT uses historical compressed files type of annual.txt, or annualof.txt of categories "Futures Only", or
"Futures-and-Options-Combined". These files have identical names for each year. Therefore, you need to rename these files.
For example, you want to use 5 files type of annual.txt. The file annual.txt for current year must be renamed in year.txt
The name "year" is the number of current year. For example, renamed files can have such names: 2015.txt,
2014.txt, 2013.txt, 2012.txt, 2011.txt.
Then, place these files into the folder Files/MQL4. Now, the indicator is ready for a work.
Maximum quantity of used files type of year.txt is 50 for this version.
How to update files code.bin every week?
The indicator creates files type of code.bin. The name "code" is market's code. So as to update these files,
do next steps:
1 Update the file year.txt for current year.
2 Open the window "Global Variables", choose the tab "Tools", or press the key F3.
3 Change the value of the variable "Update files code.bin" from 0 to 1.
4 Close the window "Global Variables".
5 Update the chart, choose the tab "Charts" and press "Refresh".
After that, all of files code.bin will be updated.
*/
#property strict
#property indicator_separate_window
#property indicator_buffers 7
#property indicator_color1 Green
#property indicator_color2 Blue
#property indicator_color3 Red
#property indicator_color4 Gray
#property indicator_color5 LightSlateGray
#property indicator_color6 LightSlateGray
#property indicator_color7 LightSlateGray
#property indicator_style1 STYLE_SOLID
#property indicator_style2 STYLE_SOLID
#property indicator_style3 STYLE_SOLID
#property indicator_style4 STYLE_SOLID
#property indicator_style5 STYLE_DOT
#property indicator_style6 STYLE_DOT
#property indicator_style7 STYLE_DOT
#property indicator_width1 2
#property indicator_width2 2
#property indicator_width3 2
#property indicator_width4 2
#property indicator_width5 1
#property indicator_width6 1
#property indicator_width7 1
//---- indicator parameters
input string Code="xxxxxx";
input int Period_0=26; // Period of COT index and WILLCO index
input int Period_1=52; // Period of OI index
input int Period_2=6; // Period of Movement index and Spread movement index
//+------------------------------------------------------------------+
//| Indicators |
//+------------------------------------------------------------------+
enum id
{
COT, // COT index
WILLCO, // WILLCO index
Spread_movement, // Spread movement index
Movement, // Movement index
Open_interest, // Open interest
Net, // Positions net
Long, // Positions long
Short, // Positions short
Pct_net, // Percent of OI for positions net
Pct_long, // Percent of OI for positions long
Pct_short // Percent of OI for positions short
};
input id Indicator=COT;
input bool OI_index=false; // OI index
input bool Large=false; // Noncommercial
input bool Comm=true; // Commercial
input bool Specs=false; // Nonreportable
input bool Overturn=false; // Overturn chart
input bool Histogram=false;
//----
bool work=true;
double zi=-1;
double l0=100;
double l1=50;
double E1[2650],E2[2650],E3[2650],az;
double Buffer0[],Buffer1[],Buffer2[],Buffer3[],Buffer4[],Buffer5[],Buffer6[];
int OI[2650],L1[2650],L2[2650],L3[2650],S1[2650],S2[2650],S3[2650],C1[2650],C2[2650],C3[2650];
datetime DT[2650];
int b,p0,p1,p2;
string c,n,w,o;
char j=2;
uint x;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
if(_Period<PERIOD_H1)
{
work=false;
return(INIT_SUCCEEDED);
}
//--- indicator buffers mapping
IndicatorBuffers(7);
SetIndexBuffer(0,Buffer0);
SetIndexBuffer(1,Buffer1);
SetIndexBuffer(2,Buffer2);
SetIndexBuffer(3,Buffer3);
SetIndexBuffer(4,Buffer4);
SetIndexBuffer(5,Buffer5);
SetIndexBuffer(6,Buffer6);
//----
if(!Histogram)
b=DRAW_LINE;
else
b=DRAW_HISTOGRAM;
//----
SetIndexStyle(0,b);
SetIndexStyle(1,b);
SetIndexStyle(2,b);
SetIndexStyle(3,b);
SetIndexStyle(4,DRAW_LINE);
SetIndexStyle(5,DRAW_LINE);
SetIndexStyle(6,DRAW_LINE);
//----
p0=Period_0;
p1=Period_1;
p2=Period_2;
//---- restrictions
if(p0<2) p0=2;
if(Indicator==2) p1=p0;
if(p1<2) p1=2;
if(p2>=p0) p2=p0;
if(p2<1) p2=1;
//----
switch(Indicator)
{
case 0: w="COT("+(string)p0+")."; break;
case 1: w="WILLCO("+(string)p0+")."; break;
case 2: w="SprMov("+(string)p0+")."; l0=60; l1=-60; break;
case 3: w="Mov("+(string)p0+")."; l0=40; l1=-40; break;
case 4: w="OI."; SetIndexLabel(3,"OI"); j=0; break;
case 5: w="Net."; j=0; break;
case 6: w="Long."; j=0; break;
case 7: w="Short."; j=0; break;
case 8: w="% Net."; break;
case 9: w="% Long."; break;
case 10: w="% Short."; break;
default: return(INIT_FAILED);
}
//----
IndicatorDigits(j);
SetIndexLabel(0,w+" Noncommercial");
SetIndexLabel(1,w+" Commercial");
SetIndexLabel(2,w+" Nonreportable");
if(Indicator<2) SetIndexLabel(3,"OI index("+(string)p1+")");
GlobalVariableSet("Update files code.bin",0);
//----
if(Overturn)
{
az=1;
zi=1;
}
//----
c=Code;
if(ObjectFind("code")==-1 || c!="xxxxxx")
{
string sc[]=
{
"GBPUSD","096742", // BRITISH POUND STERLING
"6B","096742", // BRITISH POUND STERLING
"EURUSD","099741", // EURO FX
"6E","099741", // EURO FX
"AUDUSD","232741", // AUSTRALIAN DOLLAR
"6A","232741", // AUSTRALIAN DOLLAR
"NZDUSD","112741", // NEW ZEALAND DOLLAR
"6N","112741", // NEW ZEALAND DOLLAR
"USDCAD","090741", // CANADIAN DOLLAR
"6C","090741", // CANADIAN DOLLAR
"USDCHF","092741", // SWISS FRANC
"6S","092741", // SWISS FRANC
"USDJPY","097741", // JAPANESE YEN
"6J","097741", // JAPANESE YEN
"XAUUSD","088691", // GOLD
"GOLD","088691", // GOLD
"GC","088691", // GOLD
"XAGUSD","084691", // SILVER
"SILVER","084691", // SILVER
"SI","084691", // SILVER
"HG","085692", // COPPER-GRADE #1
"PA","075651", // PALLADIUM
"PL","076651", // PLATINUM
"ZW","001602", // WHEAT-SRW
"ZC","002602", // CORN
"ZS","005602", // SOYBEANS
"ZM","026603", // SOYBEAN MEAL
"ZL","007601", // SOYBEAN OIL
"ZO","004603", // OATS
"ZR","039601", // ROUGH RICE
"CL","067651", // CRUDE OIL, LIGHT SWEET
"HO","022651", // #2 HEATING OIL
"XR","111659", // GASOLINE BLENDSTOCK (RBOB)
"NG","023651", // NATURAL GAS
"DX","098662", // U.S.DOLLAR INDEX
"ZN","043602", // 10-YEAR U.S. TREASURY NOTES
"ES","13874A", // E-MINI S&P 500 STOCK INDEX
"NQ","209742", // NASDAQ-100 STOCK INDEX (MINI)
"LE","057642", // LIVE CATTLE
"GF","061641", // FEEDER CATTLE
"HE","054642", // LEAN HOGS
"CC","073732", // COCOA - ICE FUTURES U.S
"CT","033661", // COTTON NO. 2
"KC","083731", // COFFEE C
"SB","080732" // SUGAR NO. 11
};
//----
for(j=0; j<ArraySize(sc); j++)
{
if(StringFind(_Symbol,sc[j],0)==-1) continue;
c=sc[j+1];
break;
}
//----
if(c=="xxxxxx")
{
Alert("Enter market's code!");
work=false;
}
else
if(!FileIsExist(c+".bin")) x=1;
}
else
c=ObjectDescription("code");
n=c+".bin";
//----
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
GlobalVariableDel(n);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{
//----
if(!work) return(rates_total);
int i,d,handle,f,e,z,r,s,k,g;
string v;
//---- to change global variables
if(GlobalVariableGet("Update files code.bin")==1)
{
for(i=0; i<GlobalVariablesTotal(); i++)
{
v=GlobalVariableName(i);
if(StringFind(v,".bin",6)==6) GlobalVariableSet(v,1);
}
GlobalVariableSet("Update files code.bin",0);
}
double q=GlobalVariableGet(n);
//---- to get last date
if(q==1 || x==1)
{
x=0;
int y[21200],t,n1,n2,n3,n4,n5,n6,n7,n8,n9;
string text[250],files[52],u,h,year,month,day,tx;
if(FileIsExist(n))
{
handle=FileOpen(n,FILE_READ|FILE_BIN); // <- place 1
if(handle!=INVALID_HANDLE)
{
FileSeek(handle,-4,SEEK_END);
t=FileReadInteger(handle,INT_VALUE);
FileClose(handle);
tx="updated!";
}
else
{
Alert("Error: "+(string)GetLastError()+".\nThe location of the error at the code is the place 1.");
GlobalVariableSet(n,0);
work=false;
return(rates_total);
}
}
else
tx="created!";
//---- to get the quantity of files year.txt
z=Year();
for(i=z; i>z-50; i--)
{
h=(string)i+".txt";
if(FileIsExist(h))
{
files[d]=h;
d++;
e++;
u+=h+", ";
if(e>9)
{
u+="\n";
e=0;
}
}
else
if(d>0) break;
}
//----
if(d==0)
{
Alert("There are not files year.txt at the folder Files/MQL4!");
GlobalVariableSet(n,0);
work=false;
return(rates_total);
}
else
if(tx=="created!") o="\nUsed files: "+u+"";
//---- columns for a reading
string column1="\"CFTC Contract Market Code\"";
string column2="\"As of Date in Form YYYY-MM-DD\"";
string column3="\"Open Interest (All)\"";
string column4="\"Noncommercial Positions-Long (All)\"";
string column5="\"Noncommercial Positions-Short (All)\"";
string column6="\"Commercial Positions-Long (All)\"";
string column7="\"Commercial Positions-Short (All)\"";
string column8="\"Nonreportable Positions-Long (All)\"";
string column9="\"Nonreportable Positions-Short (All)\"";
//---- to read files year.txt
for(z=0; z<d; z++)
{
i=0;
e=0;
f=0;
n1=0;
n2=0;
n3=0;
n4=0;
n5=0;
n6=0;
n7=0;
n8=0;
n9=0;
handle=FileOpen(files[z],FILE_CSV|FILE_READ,","); // <- place 2
if(handle!=INVALID_HANDLE)
{
while(!FileIsEnding(handle))
{
if(FileIsLineEnding(handle)) i=0;
i++;
text[i]=FileReadString(handle);
if(i>20) continue;
//---- to search columns
if(f<=18)
{
if(text[i]==column1) n1=i;
if(text[i]==column2) n2=i;
if(text[i]==column3) n3=i;
if(text[i]==column4) n4=i;
if(text[i]==column5) n5=i;
if(text[i]==column6) n6=i;
if(text[i]==column7) n7=i;
if(text[i]==column8) n8=i;
if(text[i]==column9) n9=i;
if(f==18)
{
if(n1==0 || n2==0 || n3==0 || n4==0 || n5==0 || n6==0 || n7==0 || n8==0 || n9==0)
{
v=" ";
if(n1==0) v+="\n"+column1;
if(n2==0) v+="\n"+column2;
if(n3==0) v+="\n"+column3;
if(n4==0) v+="\n"+column4;
if(n5==0) v+="\n"+column5;
if(n6==0) v+="\n"+column6;
if(n7==0) v+="\n"+column7;
if(n8==0) v+="\n"+column8;
if(n9==0) v+="\n"+column9;
Alert("These columns are not found at the file "+files[z]+":"+"\n"+v);
work=false;
break;
}
}
f++;
}
//----
if(i<5)
{
k=StringLen(text[i])-2;
if(StringFind(text[i],"\"",k)!=-1) r=i-1;
}
//----
if(i<20) continue;
u=StringTrimRight(text[n1+r]);
u=StringTrimLeft(u);
if(e==0)
{
if(u!=c) continue;
e=1;
if(g==0)
{
h=text[1];
if(r>0) h+=", "+text[2];
}
}
else
if(u!=c) break;
//----
year=StringSubstr(text[n2+r],0,4);
month=StringSubstr(text[n2+r],5,2);
day=StringSubstr(text[n2+r],8,2);
s=(int)StrToTime(year+"."+month+"."+day);
if(s>t)
{
y[g]=s; g++; // Date
y[g]=StrToInteger(text[n3+r]); g++; // Open interest
y[g]=StrToInteger(text[n4+r]); g++; // Noncommercial positions-long
y[g]=StrToInteger(text[n6+r]); g++; // Commercial positions-long
y[g]=StrToInteger(text[n8+r]); g++; // Nonreportable positions-long
y[g]=StrToInteger(text[n5+r]); g++; // Noncommercial positions-short
y[g]=StrToInteger(text[n7+r]); g++; // Commercial positions-short
y[g]=StrToInteger(text[n9+r]); g++; // Nonreportable positions-short
}
else
{
z=50;
break;
}
}
FileClose(handle);
if(!work) break;
}
else
{
Alert("Error: "+(string)GetLastError()+".\nThe location of the error at the code is the place 2.");
if(tx=="updated!") GlobalVariableSet(n,0);
work=false;
break;
}
//----
if(s==0)
{
Alert("The code "+c+" is not found at the file "+files[z]+"!");
work=false;
break;
}
//----
if(g==0)
{
PrintFormat("The updating of the file "+n+" for "+h+" is not required!");
GlobalVariableSet(n,0);
break;
}
//----
if(z==50) break;
}
//----
if(!work || g==0) return(rates_total);
//---- to write data to the file code.bin
handle=FileOpen(n,FILE_READ|FILE_WRITE|FILE_BIN); // <- place 3
if(handle!=INVALID_HANDLE)
{
FileSeek(handle,0,SEEK_END);
for(i=g-1; i>=0; i--)
{
x=FileWriteInteger(handle,y[i],INT_VALUE); // <- place 4
if(x!=sizeof(int))
{
work=false;
break;
}
}
FileClose(handle);
if(work)
{
if(tx=="created!")
Alert("The file "+n+" for "+h+" was "+tx+"\n"+o);
else
PrintFormat("The file "+n+" for "+h+" was "+tx);
}
else
{
Alert("Error: "+(string)GetLastError()+", at the recording to the file "+n+"."+
"\nThis file was deleted.\nThe location of the error at the code is the place 4.");
FileDelete(n);
GlobalVariableSet(n,0);
return(rates_total);
}
}
else
{
Alert("Error: "+(string)GetLastError()+".\nThe location of the error at the code is the place 3.");
GlobalVariableSet(n,0);
return(rates_total);
}
}
//---- to read the file code.bin
if(q==1 || j!=-1)
{
j=-1;
GlobalVariableSet(n,0);
if(FileIsExist(n))
{
handle=FileOpen(n,FILE_READ|FILE_BIN); // <- place 5
if(handle!=INVALID_HANDLE)
{
g=(int)(FileSize(handle)/32);
b=g;
for(i=g-1; i>=0; i--)
{
S3[i]=FileReadInteger(handle,INT_VALUE); // Nonreportable positions-short
S2[i]=FileReadInteger(handle,INT_VALUE); // Commercial positions-short
S1[i]=FileReadInteger(handle,INT_VALUE); // Noncommercial positions-short
L3[i]=FileReadInteger(handle,INT_VALUE); // Nonreportable positions-long
L2[i]=FileReadInteger(handle,INT_VALUE); // Commercial positions-long
L1[i]=FileReadInteger(handle,INT_VALUE); // Noncommercial positions-long
OI[i]=FileReadInteger(handle,INT_VALUE); // Open interest
DT[i]=(datetime)FileReadInteger(handle,INT_VALUE); // Date
C3[i]=L3[i]-S3[i]; // Nonreportable positions-net
C2[i]=L2[i]-S2[i]; // Commercial positions-net
C1[i]=L1[i]-S1[i]; // Noncommercial positions-net
E3[i]=100.0*C3[i]/OI[i]; // % of open interest for nonreportable positions-net
E2[i]=100.0*C2[i]/OI[i]; // % of open interest for commercial positions-net
E1[i]=100.0*C1[i]/OI[i]; // % of open interest for noncommercial positions-net
}
FileClose(handle);
if(ObjectFind("code")==-1)
{
ObjectCreate("code",OBJ_LABEL,0,0,0,0,0,0,0);
ObjectSet("code",OBJPROP_XDISTANCE,-50);
ObjectSet("code",OBJPROP_YDISTANCE,-50);
}
ObjectSetText("code",c,8,"Arial",CLR_NONE);
}
else
{
Alert("Error: "+(string)GetLastError()+".\nThe location of the error at the code is the place 5.");
return(0);
}
IndicatorShortName(w+" History: "+(string)b+" weeks. Last report: "+TimeToStr(DT[0],TIME_DATE)+" ");
}
else
Alert("There is not the file "+n+" at the folder Files/MQL4! For creat this file,\n"+
"change the value of global variable \""+n+"\" from 0 to 1 and update the chart.");
}
//---- calculations
if(q!=1 && rates_total==prev_calculated) return(rates_total);
double g0=0;
double g1=0;
double g2=0;
double g3=0;
d=0;
for(i=0; i<rates_total; i++)
{
if(d==-1)
{
Buffer0[i]=EMPTY_VALUE;
Buffer1[i]=EMPTY_VALUE;
Buffer2[i]=EMPTY_VALUE;
Buffer3[i]=EMPTY_VALUE;
Buffer4[i]=EMPTY_VALUE;
Buffer5[i]=EMPTY_VALUE;
Buffer6[i]=EMPTY_VALUE;
continue;
}
//----
if(time[i]<=DT[d])
{
for(f=0; f<26; f++)
{
if(time[i]>DT[d+1+f])
break;
}
d+=f;
//---- OI index
if(Indicator<3)
{
e=ArrayMaximum(OI,p1,d);
z=ArrayMinimum(OI,p1,d);
s=OI[e]-OI[z];
if(s>0) g3=100.0*(OI[d]-OI[z])/s;
}
//---- COT index
if(Indicator!=1 && Indicator<4)
{
e=ArrayMaximum(C1,p0,d);
z=ArrayMinimum(C1,p0,d);
s=C1[e]-C1[z];
if(s>0) g0=100.0*(az-zi*(C1[d]-C1[z])/s);
e=ArrayMaximum(C2,p0,d);
z=ArrayMinimum(C2,p0,d);
s=C2[e]-C2[z];
if(s>0) g1=100.0*(az-zi*(C2[d]-C2[z])/s);
e=ArrayMaximum(C3,p0,d);
z=ArrayMinimum(C3,p0,d);
s=C3[e]-C3[z];
if(s>0) g2=100.0*(az-zi*(C3[d]-C3[z])/s);
//---- Movement index
if(Indicator>=2)
{
r=d+p2;
e=ArrayMaximum(C1,p0,r);
z=ArrayMinimum(C1,p0,r);
s=C1[e]-C1[z];
if(s>0) g0=g0-100.0*(az-zi*(C1[r]-C1[z])/s);
e=ArrayMaximum(C2,p0,r);
z=ArrayMinimum(C2,p0,r);
s=C2[e]-C2[z];
if(s>0) g1=g1-100.0*(az-zi*(C2[r]-C2[z])/s);
e=ArrayMaximum(C3,p0,r);
z=ArrayMinimum(C3,p0,r);
s=C3[e]-C3[z];
if(s>0) g2=g2-100.0*(az-zi*(C3[r]-C3[z])/s);
//---- OI Movement index
if(Indicator==2)
{
e=ArrayMaximum(OI,p0,r);
z=ArrayMinimum(OI,p0,r);
s=OI[e]-OI[z];
if(s>0) g3=g3-100.0*(OI[r]-OI[z])/s;
if(zi==1) g3=-g3;
//---- Spread movement index
g0-=g3;
g1-=g3;
g2-=g3;
}
}
}
//---- WILLCO index
if(Indicator==1)
{
e=ArrayMaximum(E1,p0,d);
z=ArrayMinimum(E1,p0,d);
q=E1[e]-E1[z];
if(q>0) g0=100.0*(az-zi*(E1[d]-E1[z])/q);
e=ArrayMaximum(E2,p0,d);
z=ArrayMinimum(E2,p0,d);
q=E2[e]-E2[z];
if(q>0) g1=100.0*(az-zi*(E2[d]-E2[z])/q);
e=ArrayMaximum(E3,p0,d);
z=ArrayMinimum(E3,p0,d);
q=E3[e]-E3[z];
if(q>0) g2=100.0*(az-zi*(E3[d]-E3[z])/q);
}
//---- OI
if(Indicator==4) g3=OI[d];
//---- Net
if(Indicator==5)
{
g0=-zi*C1[d];
g1=-zi*C2[d];
g2=-zi*C3[d];
}
//---- Long
if(Indicator==6)
{
g0=L1[d];
g1=L2[d];
g2=L3[d];
}
//---- Short
if(Indicator==7)
{
g0=S1[d];
g1=S2[d];
g2=S3[d];
}
//---- % Net
if(Indicator==8)
{
g0=-zi*E1[d];
g1=-zi*E2[d];
g2=-zi*E3[d];
}
//---- % Long
if(Indicator==9)
{
g0=100.0*L1[d]/OI[d];
g1=100.0*L2[d]/OI[d];
g2=100.0*L3[d]/OI[d];
}
//---- % Short
if(Indicator==10)
{
g0=100.0*S1[d]/OI[d];
g1=100.0*S2[d]/OI[d];
g2=100.0*S3[d]/OI[d];
}
d++;
}
//----
if(d==0) continue;
if(Indicator<4)
{
if(Large) Buffer0[i]=g0;
if(Comm) Buffer1[i]=g1;
if(Specs) Buffer2[i]=g2;
Buffer4[i]=l0;
Buffer5[i]=l1;
Buffer6[i]=0;
if(Indicator<2)
{
if(OI_index)
{
if(d>b-p1)
Buffer3[i]=EMPTY_VALUE;
else
Buffer3[i]=g3;
}
if(d>b-p0) d=-1;
}
else
if(d>b-p0-p2) d=-1;
}
else
{
if(Indicator>4)
{
if(Large) Buffer0[i]=g0;
if(Comm) Buffer1[i]=g1;
if(Specs) Buffer2[i]=g2;
}
else
Buffer3[i]=g3;
if(Indicator==5 || Indicator==8) Buffer4[i]=0;
if(d>=b) d=-1;
}
}
//--- return value of prev_calculated for next call
return(rates_total);
}
//+------------------------------------------------------------------+
Comments