506 lines
No EOL
48 KiB
MQL5
506 lines
No EOL
48 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| OptionsPrime_v00.mq5 |
|
|
//| Copyright 2024, MetaQuotes Ltd. |
|
|
//| https://www.mql5.com |
|
|
//+------------------------------------------------------------------+
|
|
#define SWAP(A, B) { A += B; B = A - B; A -= B; }
|
|
#define SORT(a,b,c) {if(a > b) SWAP(a,b) if(a > c) SWAP(a,c) if (b>c) SWAP(b,c) }
|
|
//+------------------------------------------------------------------+
|
|
//| Variáveis Globais |
|
|
//+------------------------------------------------------------------+
|
|
enum CalcMode
|
|
{
|
|
calcOPM, // Arthur Option Price Model
|
|
calcMedian, // Median
|
|
calcLast, // Watch: Last
|
|
calcHalfAskBid, // Watch: (Ask+Bid)/2
|
|
calcAWP, // Watch: AWP
|
|
};
|
|
//+------------------------------------------------------------------+
|
|
//| Setup |
|
|
//+------------------------------------------------------------------+
|
|
double iAlavangabem = 2.0; // Cotas para cada Adjacente:
|
|
//+------------------------------------------------------------------+
|
|
//| Inputs |
|
|
//+------------------------------------------------------------------+
|
|
sinput datetime inMaxExpiration = D'2024.12.31 23:59:59'; //Expiração máxima:
|
|
sinput CalcMode inCalcMode = calcMedian; // Modo de Calculo:
|
|
sinput double inR0 = 10.75; // Taxa de Retorno Seguro:
|
|
sinput int iFrequency = 2000; // Frequencia de execucao (milisegundos):
|
|
sinput double inPcDownB = 0.0; // Porcentagem que o B pode baixar (%):
|
|
//+------------------------------------------------------------------+
|
|
//| Expert initialization function |
|
|
//+------------------------------------------------------------------+
|
|
int OnInit()
|
|
{
|
|
//--- create timer
|
|
ChartSetInteger(0,CHART_SHOW_DATE_SCALE,1);
|
|
ChartSetInteger(0,CHART_SHOW_PRICE_SCALE,1);
|
|
EventSetMillisecondTimer(iFrequency);
|
|
|
|
//---
|
|
return(INIT_SUCCEEDED);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Expert deinitialization function |
|
|
//+------------------------------------------------------------------+
|
|
void OnDeinit(const int reason)
|
|
{
|
|
//--- destroy timer
|
|
EventKillTimer();
|
|
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Expert tick function |
|
|
//+------------------------------------------------------------------+
|
|
void OnTick()
|
|
{
|
|
//---
|
|
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Timer function |
|
|
//+------------------------------------------------------------------+
|
|
void OnTimer()
|
|
{
|
|
|
|
datetime timeStart = TimeLocal();
|
|
|
|
double dbCall_Volume=0.0;
|
|
double dbCall_B0m=0.0;
|
|
double dbCall_K0m=0.0;
|
|
double dbCall_Km=0.0;
|
|
double dbCall_Xm=0.0;
|
|
|
|
double dbPut_Volume=0.0;
|
|
double dbPut_B0m=0.0;
|
|
double dbPut_K0m=0.0;
|
|
double dbPut_Km=0.0;
|
|
double dbPut_Xm=0.0;
|
|
|
|
double dbSobraTotal=0.0;
|
|
|
|
string strComment = StringFormat(
|
|
">>Expiration: %s | Calc Mode: %s | R0: %.2f%% | Frequency: %d | Down B: %.2f%%\n",
|
|
TimeToString(inMaxExpiration, TIME_DATE),
|
|
EnumToString((CalcMode)inCalcMode),
|
|
inR0 * 100,
|
|
iFrequency,
|
|
inPcDownB
|
|
);
|
|
|
|
strComment+="\nSymbol T S K0 X0 B0 Xr(OPM) --> Roll to T K X(OPM) B E a.a.(E) = dT dK dX0 dX dB By --> dR$\n";
|
|
ulong ulPositionTicket=0;
|
|
for(int i=0;i<PositionsTotal();i++)
|
|
{
|
|
ulPositionTicket=PositionGetTicket(i);
|
|
double dbS = 0.0;
|
|
double dbK = 0.0;
|
|
double dbX0 = 0.0;
|
|
double dbB0 = 0.0;
|
|
double dbX = 0.0;
|
|
double dbZ = 0.0;
|
|
string strPositonSymbol = PositionGetSymbol(i);
|
|
if(
|
|
(SymbolInfoDouble(strPositonSymbol, SYMBOL_OPTION_STRIKE) > 0.0) &&
|
|
((SymbolInfoInteger(strPositonSymbol, SYMBOL_OPTION_RIGHT) == SYMBOL_OPTION_RIGHT_CALL) || (SymbolInfoInteger(strPositonSymbol, SYMBOL_OPTION_RIGHT) == SYMBOL_OPTION_RIGHT_PUT))
|
|
)
|
|
{
|
|
|
|
dbZ=(SymbolInfoInteger(strPositonSymbol,SYMBOL_OPTION_RIGHT)==SYMBOL_OPTION_RIGHT_CALL?1.0:(SymbolInfoInteger(strPositonSymbol,SYMBOL_OPTION_RIGHT)==SYMBOL_OPTION_RIGHT_PUT?-1.0:0.0));
|
|
dbS=SymbolPrice(OptionBasis(PositionGetSymbol(i)),inCalcMode);
|
|
dbK=SymbolInfoDouble(PositionGetSymbol(i),SYMBOL_OPTION_STRIKE);
|
|
dbX0=PositionGetDouble(POSITION_PRICE_OPEN);
|
|
dbB0=dbK+dbX0*dbZ;
|
|
//dbX=SymbolPrice(strPositonSymbol,inCalcMode);
|
|
dbX=(SymbolPrice(strPositonSymbol,inCalcMode)>0.0?SymbolPrice(strPositonSymbol,inCalcMode):ArthurOptionPriceModel(strPositonSymbol));
|
|
if(SymbolInfoInteger(strPositonSymbol,SYMBOL_OPTION_RIGHT)==SYMBOL_OPTION_RIGHT_CALL)
|
|
{
|
|
dbCall_Volume+=PositionGetDouble(POSITION_VOLUME);
|
|
dbCall_B0m+=(dbB0*PositionGetDouble(POSITION_VOLUME));
|
|
dbCall_K0m+=(dbK*PositionGetDouble(POSITION_VOLUME));
|
|
}
|
|
else
|
|
if(SymbolInfoInteger(strPositonSymbol,SYMBOL_OPTION_RIGHT)==SYMBOL_OPTION_RIGHT_PUT)
|
|
{
|
|
dbPut_Volume+=PositionGetDouble(POSITION_VOLUME);
|
|
dbPut_B0m+=(dbB0*PositionGetDouble(POSITION_VOLUME));
|
|
dbPut_K0m+=(dbK*PositionGetDouble(POSITION_VOLUME));
|
|
}
|
|
|
|
for(int s=0;s<=SymbolsTotal(false);s++)
|
|
{
|
|
if(
|
|
(SymbolInfoDouble(SymbolName(s,false),SYMBOL_OPTION_STRIKE)>0.0)
|
|
&& (OptionBasis(SymbolName(s,false))==OptionBasis(strPositonSymbol))
|
|
&& ( (SymbolInfoInteger(SymbolName(s,false),SYMBOL_OPTION_RIGHT)==SYMBOL_OPTION_RIGHT_CALL)||(SymbolInfoInteger(SymbolName(s,false),SYMBOL_OPTION_RIGHT)==SYMBOL_OPTION_RIGHT_PUT) )
|
|
&& SymbolInfoInteger(SymbolName(s,false),SYMBOL_EXPIRATION_TIME)>=(TimeLocal()+(24*60*60))
|
|
&& SymbolInfoInteger(SymbolName(s,false),SYMBOL_EXPIRATION_TIME)<=inMaxExpiration
|
|
)
|
|
{
|
|
SymbolSelect(SymbolName(s,false),true);
|
|
}
|
|
}
|
|
|
|
double _BestEBaa=0.0;
|
|
double _BestE=0.0;
|
|
string _BestEBaaSymbol="";
|
|
double _S[]; ArrayResize(_S,SymbolsTotal(true));
|
|
long _T[]; ArrayResize(_T,SymbolsTotal(true));
|
|
double _Z[]; ArrayResize(_Z,SymbolsTotal(true));
|
|
double _K[]; ArrayResize(_K,SymbolsTotal(true));
|
|
double _X[]; ArrayResize(_X,SymbolsTotal(true));
|
|
double _r[]; ArrayResize(_r,SymbolsTotal(true));
|
|
double _B[]; ArrayResize(_B,SymbolsTotal(true));
|
|
double _I[]; ArrayResize(_I,SymbolsTotal(true));
|
|
double _E[]; ArrayResize(_E,SymbolsTotal(true));
|
|
double _EBaa[]; ArrayResize(_EBaa,SymbolsTotal(true));
|
|
double _Xopm[]; ArrayResize(_Xopm,SymbolsTotal(true));
|
|
for(int s=0;s<=SymbolsTotal(true);s++)
|
|
{
|
|
|
|
if(
|
|
(SymbolInfoDouble(SymbolName(s,true),SYMBOL_OPTION_STRIKE)>0.0)
|
|
&& (OptionBasis(SymbolName(s,true))==OptionBasis(strPositonSymbol))
|
|
&& SymbolInfoInteger(SymbolName(s,true),SYMBOL_EXPIRATION_TIME)>TimeLocal()
|
|
&& SymbolInfoInteger(SymbolName(s,true),SYMBOL_EXPIRATION_TIME)<=inMaxExpiration
|
|
)
|
|
{
|
|
|
|
_S[s]=SymbolPrice(OptionBasis(SymbolName(s,true)),inCalcMode);
|
|
_T[s]=SymbolInfoInteger(SymbolName(s,true),SYMBOL_EXPIRATION_TIME);
|
|
_Z[s]=(SymbolInfoInteger(SymbolName(s,true),SYMBOL_OPTION_RIGHT)==SYMBOL_OPTION_RIGHT_CALL?1.0:(SymbolInfoInteger(SymbolName(s,true),SYMBOL_OPTION_RIGHT)==SYMBOL_OPTION_RIGHT_PUT?-1.0:0.0));
|
|
_K[s]=SymbolInfoDouble(SymbolName(s,true),SYMBOL_OPTION_STRIKE);
|
|
_X[s]=SymbolPrice(SymbolName(s,true),inCalcMode);
|
|
_r[s]=_X[s]/_S[s]; //_r[s]=_X[s]/_K[s];
|
|
_B[s]=_K[s]+_X[s]*_Z[s];
|
|
if(SymbolInfoInteger(SymbolName(s,true),SYMBOL_OPTION_RIGHT)==SYMBOL_OPTION_RIGHT_CALL) _I[s]=MathMax(_S[s]-_K[s],0.0); // _I[s]=(_S[s]>_K[s]?_S[s]-_K[s]:0.0);
|
|
if(SymbolInfoInteger(SymbolName(s,true),SYMBOL_OPTION_RIGHT)==SYMBOL_OPTION_RIGHT_PUT) _I[s]=MathMax(_K[s]-_S[s],0.0); //(_K[s]>_S[s]?_K[s]-_S[s]:0.0);
|
|
_E[s]=MathMax(_X[s]-_I[s],0.0);
|
|
// ((_X[s]-(_I[s]>0.0?_I[s]:0.0))>0.0?_X[s]-(_I[s]>0.0?_I[s]:0.0):0.0); // _E[s]=_E[s]*2.0;;_E[s]=0.0;
|
|
if(SymbolInfoInteger(SymbolName(s,true),SYMBOL_OPTION_RIGHT)==SYMBOL_OPTION_RIGHT_CALL)
|
|
{
|
|
_EBaa[s]=pow(1.0+(2.0*_E[s])/_S[s],252.0/((double)(_T[s]-TimeLocal())/86000.0))-1.0;
|
|
}
|
|
else
|
|
if(SymbolInfoInteger(SymbolName(s,true),SYMBOL_OPTION_RIGHT)==SYMBOL_OPTION_RIGHT_PUT)
|
|
{
|
|
_EBaa[s]=pow(1.0+_E[s]/_S[s],252.0/((double)(_T[s]-TimeLocal())/86000.0))-1.0;
|
|
}
|
|
_Xopm[s]=ArthurOptionPriceModel(SymbolName(s,true));
|
|
|
|
/*
|
|
if(_Z[s]==(SymbolInfoInteger(strPositonSymbol,SYMBOL_OPTION_RIGHT)==SYMBOL_OPTION_RIGHT_CALL?1.0:-1.0))
|
|
if((SymbolInfoInteger(strPositonSymbol,SYMBOL_OPTION_RIGHT)==SYMBOL_OPTION_RIGHT_CALL)?_B[s]>(dbB0*(1.0-inPcDownB/100)):(SymbolInfoInteger(strPositonSymbol,SYMBOL_OPTION_RIGHT)==SYMBOL_OPTION_RIGHT_PUT?_B[s]<(dbB0*(1.0+inPcDownB/100)) : false ) )
|
|
if(_X[s]>dbX)
|
|
//if(dbX0>dbX)
|
|
{
|
|
_BestEBaaSymbol=SymbolName(s,true);
|
|
_BestEBaa=_EBaa[s];
|
|
_BestE=_E[s];
|
|
}
|
|
*/
|
|
|
|
if( SymbolName(s,true)!=strPositonSymbol)
|
|
if(SymbolInfoInteger(SymbolName(s,true),SYMBOL_EXPIRATION_TIME)>=SymbolInfoInteger(strPositonSymbol,SYMBOL_EXPIRATION_TIME))
|
|
if(_X[s]>dbX)
|
|
if(SymbolInfoInteger(strPositonSymbol,SYMBOL_OPTION_RIGHT)==SYMBOL_OPTION_RIGHT_CALL )
|
|
{
|
|
if(_B[s]>=dbB0)
|
|
if(_Z[s]>0.0)
|
|
{
|
|
if(_EBaa[s]>_BestEBaa)
|
|
{
|
|
_BestEBaaSymbol=SymbolName(s,true);
|
|
_BestEBaa=_EBaa[s];
|
|
_BestE=_E[s];
|
|
}
|
|
}
|
|
}
|
|
else
|
|
if(SymbolInfoInteger(strPositonSymbol,SYMBOL_OPTION_RIGHT)==SYMBOL_OPTION_RIGHT_PUT )
|
|
{
|
|
if(_B[s]<=dbB0)
|
|
if(_Z[s]<=0.0)
|
|
{
|
|
_BestEBaaSymbol=SymbolName(s,true);
|
|
_BestEBaa=_EBaa[s];
|
|
_BestE=_E[s];
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
strComment+=strPositonSymbol+(strPositonSymbol.Length()==8?" ":"")+": ";
|
|
strComment+=IntegerToString( ( SymbolInfoInteger(strPositonSymbol,SYMBOL_EXPIRATION_TIME) - TimeLocal() )/86400 )+"d "; // " 73d ";
|
|
strComment+=DoubleToString(dbS,2)+" ";
|
|
strComment+=DoubleToString(dbK,2)+" ";
|
|
strComment+=DoubleToString(dbX0,2)+" ";
|
|
strComment+=DoubleToString(dbB0,2)+" ";
|
|
strComment+=DoubleToString(dbX,2)+"(";
|
|
strComment+=DoubleToString(ArthurOptionPriceModel(strPositonSymbol),2)+") ";
|
|
if(_BestEBaaSymbol.Length()>0)
|
|
{
|
|
if(SymbolInfoInteger(_BestEBaaSymbol,SYMBOL_OPTION_RIGHT)==SYMBOL_OPTION_RIGHT_CALL)
|
|
{
|
|
dbCall_Km+=SymbolInfoDouble(_BestEBaaSymbol, SYMBOL_OPTION_STRIKE)*PositionGetDouble(POSITION_VOLUME);
|
|
dbCall_Xm+=SymbolPrice(_BestEBaaSymbol,inCalcMode)*PositionGetDouble(POSITION_VOLUME);
|
|
}
|
|
else
|
|
if(SymbolInfoInteger(_BestEBaaSymbol,SYMBOL_OPTION_RIGHT)==SYMBOL_OPTION_RIGHT_PUT)
|
|
{
|
|
dbPut_Km+=SymbolInfoDouble(_BestEBaaSymbol, SYMBOL_OPTION_STRIKE)*PositionGetDouble(POSITION_VOLUME);
|
|
dbPut_Xm+=SymbolPrice(_BestEBaaSymbol,inCalcMode)*PositionGetDouble(POSITION_VOLUME);
|
|
}
|
|
|
|
strComment+=" --> ";
|
|
strComment+=_BestEBaaSymbol+(_BestEBaaSymbol.Length()==8?" ":"")+" ";
|
|
strComment+=DoubleToString( (double)( (SymbolInfoInteger(_BestEBaaSymbol,SYMBOL_EXPIRATION_TIME) - TimeLocal() ) / 86000.0 ) , 0 ) + "d ";
|
|
strComment+=DoubleToString(SymbolInfoDouble(_BestEBaaSymbol, SYMBOL_OPTION_STRIKE),2) + " ";
|
|
strComment+=DoubleToString(SymbolPrice(_BestEBaaSymbol,inCalcMode), 2 ) + "(";
|
|
strComment+=DoubleToString(ArthurOptionPriceModel(_BestEBaaSymbol), 2 ) + ") ";
|
|
strComment+=DoubleToString(SymbolInfoDouble(_BestEBaaSymbol, SYMBOL_OPTION_STRIKE)+SymbolPrice(_BestEBaaSymbol,inCalcMode)*dbZ,2)+ " ";
|
|
|
|
if(SymbolInfoInteger(_BestEBaaSymbol,SYMBOL_OPTION_RIGHT)==SYMBOL_OPTION_RIGHT_CALL)
|
|
{
|
|
strComment+=DoubleToString(
|
|
//(SymbolPrice(_BestEBaaSymbol,inCalcMode)-(dbS-SymbolInfoDouble(_BestEBaaSymbol, SYMBOL_OPTION_STRIKE)>0.0?dbS-SymbolInfoDouble(_BestEBaaSymbol, SYMBOL_OPTION_STRIKE):0.0)>0.0?SymbolPrice(_BestEBaaSymbol,inCalcMode)-(dbS-SymbolInfoDouble(_BestEBaaSymbol, SYMBOL_OPTION_STRIKE)>0.0?dbS-SymbolInfoDouble(_BestEBaaSymbol, SYMBOL_OPTION_STRIKE):0.0):0.0)
|
|
_BestE
|
|
, 2 ) + " ";
|
|
}
|
|
else
|
|
if(SymbolInfoInteger(_BestEBaaSymbol,SYMBOL_OPTION_RIGHT)==SYMBOL_OPTION_RIGHT_PUT)
|
|
{
|
|
strComment+=DoubleToString(
|
|
//SymbolPrice(_BestEBaaSymbol,inCalcMode)-
|
|
//((SymbolInfoDouble(_BestEBaaSymbol, SYMBOL_OPTION_STRIKE)-dbS)>0.0?(SymbolInfoDouble(_BestEBaaSymbol, SYMBOL_OPTION_STRIKE)-dbS):0.0)
|
|
_BestE
|
|
, 2 ) + " ";
|
|
}
|
|
|
|
//strComment+="("+DoubleToString(100*( (_BestE/dbS) ), 2 )+"%) ";
|
|
strComment+="("+DoubleToString(100*( pow(1.0+((_BestE*2.0)/dbS),252.0/((double)(SymbolInfoInteger(_BestEBaaSymbol,SYMBOL_EXPIRATION_TIME)-TimeLocal())/86000.0))-1.0 ), 2 )+"%) ";
|
|
|
|
strComment+=" = ";
|
|
strComment+=DoubleToString( (( (SymbolInfoInteger(_BestEBaaSymbol,SYMBOL_EXPIRATION_TIME) - TimeLocal() ) / 86000.0 ))-(( SymbolInfoInteger(strPositonSymbol,SYMBOL_EXPIRATION_TIME) - TimeLocal() )/86400 ), 0 )+"d ";
|
|
if(SymbolInfoInteger(_BestEBaaSymbol, SYMBOL_OPTION_RIGHT)==SYMBOL_OPTION_RIGHT_CALL)
|
|
{
|
|
strComment+=DoubleToString( SymbolInfoDouble(_BestEBaaSymbol, SYMBOL_OPTION_STRIKE)-dbK, 2) + " ";
|
|
}
|
|
else
|
|
if(SymbolInfoInteger(_BestEBaaSymbol, SYMBOL_OPTION_RIGHT)==SYMBOL_OPTION_RIGHT_PUT)
|
|
{
|
|
strComment+=DoubleToString( dbK-SymbolInfoDouble(_BestEBaaSymbol, SYMBOL_OPTION_STRIKE), 2) + " ";
|
|
}
|
|
strComment+=DoubleToString( dbX0-dbX, 2 ) + " ";
|
|
strComment+=DoubleToString(SymbolPrice(_BestEBaaSymbol,inCalcMode)-dbX,2)+" ";
|
|
if(SymbolInfoInteger(_BestEBaaSymbol,SYMBOL_OPTION_RIGHT)==SYMBOL_OPTION_RIGHT_CALL) strComment+=DoubleToString((SymbolInfoDouble(_BestEBaaSymbol, SYMBOL_OPTION_STRIKE)+SymbolPrice(_BestEBaaSymbol,inCalcMode))-dbB0,2)+" ";
|
|
if(SymbolInfoInteger(_BestEBaaSymbol,SYMBOL_OPTION_RIGHT)==SYMBOL_OPTION_RIGHT_PUT) strComment+=DoubleToString(dbB0-(SymbolInfoDouble(_BestEBaaSymbol, SYMBOL_OPTION_STRIKE)-SymbolPrice(_BestEBaaSymbol,inCalcMode)),2)+" ";
|
|
|
|
double dbYB=(SymbolInfoDouble(_BestEBaaSymbol, SYMBOL_OPTION_STRIKE)+SymbolPrice(_BestEBaaSymbol,inCalcMode))-dbB0;
|
|
strComment+="("+DoubleToString(dbYB,2)+"%)";
|
|
|
|
dbSobraTotal+=(SymbolPrice(_BestEBaaSymbol,inCalcMode)-dbX)*PositionGetDouble(POSITION_VOLUME);
|
|
strComment+=" --> "+DoubleToString( (SymbolPrice(_BestEBaaSymbol,inCalcMode)-dbX)*PositionGetDouble(POSITION_VOLUME),2);
|
|
|
|
}
|
|
else
|
|
{
|
|
if( SymbolInfoInteger(PositionGetSymbol(i),SYMBOL_OPTION_RIGHT)==SYMBOL_OPTION_RIGHT_CALL)
|
|
{
|
|
dbCall_Km+=(dbK*PositionGetDouble(POSITION_VOLUME));
|
|
dbCall_Xm+=(dbX0*PositionGetDouble(POSITION_VOLUME));
|
|
}
|
|
else
|
|
if( SymbolInfoInteger(PositionGetSymbol(i),SYMBOL_OPTION_RIGHT)==SYMBOL_OPTION_RIGHT_PUT)
|
|
{
|
|
dbPut_Km+=(dbK*PositionGetDouble(POSITION_VOLUME));
|
|
dbPut_Xm+=(dbX0*PositionGetDouble(POSITION_VOLUME));
|
|
}
|
|
}
|
|
strComment+="\n";
|
|
}
|
|
else
|
|
{
|
|
}
|
|
|
|
}
|
|
|
|
dbCall_K0m=dbCall_K0m/dbCall_Volume;
|
|
dbCall_B0m=dbCall_B0m/dbCall_Volume;
|
|
dbCall_Km=dbCall_Km/dbCall_Volume;
|
|
dbCall_Xm=dbCall_Xm/dbCall_Volume;
|
|
strComment+="------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n";
|
|
strComment+="CALL: ";
|
|
strComment+=DoubleToString(dbCall_K0m,2)+" ";
|
|
strComment+=DoubleToString(dbCall_B0m-dbCall_K0m,2)+" ";
|
|
strComment+=DoubleToString(dbCall_B0m,2)+" ";
|
|
strComment+=" --> ";
|
|
strComment+=" "+DoubleToString(dbCall_Km,2)+" ";
|
|
strComment+=""+DoubleToString(dbCall_Xm,2)+" ";
|
|
strComment+=" ";
|
|
strComment+=DoubleToString(dbCall_Km+dbCall_Xm,2)+" ";
|
|
strComment+="\n";
|
|
|
|
dbPut_K0m=dbPut_K0m/dbPut_Volume;
|
|
dbPut_B0m=dbPut_B0m/dbPut_Volume;
|
|
dbPut_Km=dbPut_Km/dbPut_Volume;
|
|
dbPut_Xm=dbPut_Xm/dbPut_Volume;
|
|
strComment+="PUT: ";
|
|
strComment+=DoubleToString(dbPut_K0m,2)+" ";
|
|
strComment+=DoubleToString(dbPut_K0m-dbPut_B0m,2)+" ";
|
|
strComment+=DoubleToString(dbPut_B0m,2)+" ";
|
|
strComment+=" --> ";
|
|
strComment+=" "+DoubleToString(dbPut_Km,2)+" ";
|
|
strComment+=""+DoubleToString(dbPut_Xm,2)+" ";
|
|
strComment+=" ";
|
|
strComment+=DoubleToString(dbPut_Km-dbPut_Xm,2)+" ";
|
|
strComment+=" --> "+DoubleToString(dbSobraTotal,2);
|
|
strComment+="\n";
|
|
strComment+="------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n";
|
|
|
|
// Condições para identificar Fundos de Investimento Imobiliário (FII) e FIIs com último preço maior que o preço mínimo definido
|
|
int fii_count = 0; // Inicializa a contagem de Fundos de Investimento Imobiliário (FII)
|
|
double dbSpotVolum=0.0;
|
|
double dbOptionsVolume= 0.0;
|
|
for(int i = 0; i < PositionsTotal(); i++)
|
|
{
|
|
ulPositionTicket=PositionGetTicket(i);
|
|
string symbol_name = PositionGetSymbol(i);
|
|
if((StringSubstr(SymbolInfoString(symbol_name, SYMBOL_ISIN),6,3) == "CTF") &&
|
|
(StringLen(symbol_name) == 6) &&
|
|
(StringSubstr(symbol_name, 4, 2) == "11") &&
|
|
(StringSubstr(SymbolInfoString(symbol_name, SYMBOL_DESCRIPTION),0,3) == "FII") &&
|
|
(SymbolInfoDouble(symbol_name, SYMBOL_LAST) > 0.0))
|
|
{
|
|
fii_count++;
|
|
}
|
|
if(
|
|
(PositionGetSymbol(i)=="BOVA11")||(SymbolInfoInteger(symbol_name, SYMBOL_OPTION_RIGHT) == SYMBOL_OPTION_RIGHT_PUT)
|
|
)
|
|
{
|
|
dbSpotVolum+=PositionGetDouble(POSITION_VOLUME);
|
|
}
|
|
if((SymbolInfoDouble(symbol_name, SYMBOL_OPTION_STRIKE) > 0.0) &&
|
|
((SymbolInfoInteger(symbol_name, SYMBOL_OPTION_RIGHT) == SYMBOL_OPTION_RIGHT_CALL) ) && //|| (SymbolInfoInteger(symbol_name, SYMBOL_OPTION_RIGHT) == SYMBOL_OPTION_RIGHT_PUT)) &&
|
|
(SymbolInfoInteger(symbol_name, SYMBOL_EXPIRATION_TIME) < D'2025.12.31 23:00:00') &&
|
|
(SymbolInfoInteger(symbol_name, SYMBOL_EXPIRATION_TIME) > TimeLocal()) )
|
|
{
|
|
dbOptionsVolume+=PositionGetDouble(POSITION_VOLUME);
|
|
}
|
|
}
|
|
|
|
if(fii_count>0)
|
|
{
|
|
strComment+="\nALERT: "+IntegerToString(fii_count)+" FII's\n";
|
|
}
|
|
|
|
if(dbSpotVolum*2==dbOptionsVolume)
|
|
{
|
|
}
|
|
else
|
|
{
|
|
if((dbSpotVolum*2)>dbOptionsVolume)
|
|
{
|
|
strComment+="\nALERT: Falta vender " + DoubleToString( (dbSpotVolum*2)-dbOptionsVolume, 0 ) + " opções!\n\n";
|
|
}
|
|
else
|
|
{
|
|
strComment+="\nALERT: Falta comprar " + DoubleToString( dbOptionsVolume-(dbSpotVolum*2), 0 ) + " opções!\n\n";
|
|
}
|
|
}
|
|
|
|
datetime timeEnd = TimeLocal();
|
|
long timeElapsed = timeEnd - timeStart;
|
|
strComment+=TimeToString(TimeLocal(),TIME_DATE|TIME_MINUTES|TIME_SECONDS)+". Executado em " + IntegerToString(timeElapsed) + "s\n";
|
|
Comment(strComment);
|
|
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Ativo subjacente da opção |
|
|
//+------------------------------------------------------------------+
|
|
string OptionBasis(const string strSymbol)
|
|
{
|
|
string strReturn=StringSubstr(SymbolInfoString(strSymbol,SYMBOL_ISIN),2,4);
|
|
if(StringSubstr(SymbolInfoString(strSymbol, SYMBOL_ISIN), 6, 1)=="9")
|
|
{
|
|
strReturn+="11";
|
|
}
|
|
else
|
|
{
|
|
strReturn+=StringSubstr(SymbolInfoString(strSymbol,SYMBOL_ISIN),6,1);
|
|
}
|
|
|
|
return strReturn;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Mediana |
|
|
//+------------------------------------------------------------------+
|
|
double TrueMedian(double first, double second,double third)
|
|
{
|
|
SORT(first,second,third);
|
|
return((third<=0.0)?0.0:((second<=0.0)?third:((first<=0.0)?((third+second)/2.0):second)));
|
|
};
|
|
//+------------------------------------------------------------------+
|
|
//| Preço do Símbolo |
|
|
//+------------------------------------------------------------------+
|
|
double SymbolPrice(const string SYMBOL, const CalcMode CALCMODE)
|
|
{
|
|
double result = 0.0;
|
|
switch(CALCMODE)
|
|
{
|
|
|
|
case calcOPM:
|
|
if(SymbolInfoDouble(SYMBOL,SYMBOL_OPTION_STRIKE)>0.0)
|
|
{
|
|
return ArthurOptionPriceModel(SYMBOL);
|
|
}
|
|
else
|
|
{
|
|
return(TrueMedian(SymbolInfoDouble(SYMBOL,SYMBOL_BID),SymbolInfoDouble(SYMBOL,SYMBOL_ASK),SymbolInfoDouble(SYMBOL,SYMBOL_LAST)));
|
|
}
|
|
break;
|
|
|
|
case calcLast:
|
|
result=SymbolInfoDouble(SYMBOL,SYMBOL_LAST);
|
|
break;
|
|
|
|
case calcHalfAskBid:
|
|
if((SymbolInfoDouble(SYMBOL,SYMBOL_ASK)>0.0)&&(SymbolInfoDouble(SYMBOL,SYMBOL_BID)>0.0))
|
|
result=(SymbolInfoDouble(SYMBOL,SYMBOL_ASK)+SymbolInfoDouble(SYMBOL,SYMBOL_BID))/2.0;
|
|
break;
|
|
|
|
case calcAWP:
|
|
result=SymbolInfoDouble(SYMBOL,SYMBOL_SESSION_AW);
|
|
break;
|
|
|
|
case calcMedian:
|
|
result=TrueMedian(SymbolInfoDouble(SYMBOL,SYMBOL_BID),SymbolInfoDouble(SYMBOL,SYMBOL_ASK),SymbolInfoDouble(SYMBOL,SYMBOL_LAST));
|
|
break;
|
|
|
|
}
|
|
|
|
//if(SymbolInfoDouble(SYMBOL,SYMBOL_OPTION_STRIKE)>0.0) if(result<=0.0) result=ArthurOptionPriceModel(SYMBOL);
|
|
|
|
return(result);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Arthur Options Price Model |
|
|
//+------------------------------------------------------------------+
|
|
double ArthurOptionPriceModel(string SYMBOL)
|
|
{
|
|
double _z = (SymbolInfoInteger(SYMBOL,SYMBOL_OPTION_RIGHT)==SYMBOL_OPTION_RIGHT_CALL?1.0:-1.0);
|
|
double _S = SymbolPrice( OptionBasis( SYMBOL ), inCalcMode );
|
|
double _K = SymbolInfoDouble(SYMBOL,SYMBOL_OPTION_STRIKE);
|
|
double _T = MathMax(0.0,(SymbolInfoInteger(SYMBOL,SYMBOL_EXPIRATION_TIME)-TimeLocal())/86400.0);
|
|
double _r0 = inR0;
|
|
|
|
double term1 = pow(_K - _S, 2.0);
|
|
double term2 = 4 * (_T/365.0) * pow( _r0 * _S, 2.0 );
|
|
double sqrt_term = sqrt( term1 + term2 );
|
|
|
|
return 0.5 * ( sqrt_term - _z*(_K - _S) );
|
|
} |