Stocks/Stocks.mq5
super.admin 95d062640d convert
2025-05-30 16:26:32 +02:00

611 lines
60 KiB
MQL5

//+------------------------------------------------------------------+
//| Stocks.mq5 |
//| Copyright 2022, 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) }
//+------------------------------------------------------------------+
//| Estruturas |
//+------------------------------------------------------------------+
enum CalcMode
{
VWAP,//Session Average Weighted
Last,//Last deal quote
AskBidWatch,//Watch(Ask+Bid)/2
Median//Mediana
};
enum GridLoweLimitType
{
MinHistoric,//Mínima histórica
MinHistoric_Minus50pcToZero,//Mínima histórica menos 50% até Zero
One_Mili,//0,001
One_Cents,//0,01
Two_Half_Cents,//0,025
Ten_Cents,//0,1
One_Money,//1
Customized//Especificar:
};
struct stcDeal
{
long lPositionID;
string strSymbol;
ENUM_DEAL_TYPE enType;
ulong dtTime;
double dbVolume;
double dbPrice;
/*------------------------------
long lTicket;
long lOrder;
long lTime_msc;
ENUM_DEAL_ENTRY enEntry;
long lMagic;
ENUM_DEAL_REASON enReason;
double dbComission;
double dbSwap;
double dbProfit;
double dbFee;
double dbSL;
double dbTP;
string strComment;
---------------------------------*/
double dbYield;
};
//+------------------------------------------------------------------+
//| Entradas |
//+------------------------------------------------------------------+
sinput group "Setup Financeiro";
sinput double inpFinancialTicket=100.0;//Ficha financeira (brl):
sinput double inpBalanceCorrection=0.0;//Correção do Patrimônio (brl):
sinput group "Análises";
sinput CalcMode inpCalcMode=Median;//Modo de Cálculo:
sinput ulong inpRatesQuantidade=52;//Quantidade de dias:
sinput bool inpLoadGraph=false;//Carrega o gráfico da melhor operação:
sinput group "Grid";
sinput bool inpGrid=true;//Mostra Grid?
sinput bool inpLastPriceToBase;//Ancorar na última operação?
sinput double inpGridVolume=0.0;//Volume no Grid:
sinput double inpGridSec=1.0;//Segmentações dos níveis do Grid:
sinput GridLoweLimitType inpGridLowerType=Ten_Cents;//Limite inferior da grade:
sinput double inpGridLowerLimit=0.5;//Limite inferior personalizado (brl):
//+------------------------------------------------------------------+
//| Variáveis Globais |
//+------------------------------------------------------------------+
double gdbBalance=inpBalanceCorrection;//Saldo (brl):
double gdbEquity=0.0;
string strComment="";
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
Comment(StringFormat("\nBalancey: %.2f, Equity: %.2f",inpBalanceCorrection,AccountInfoDouble(ACCOUNT_EQUITY)));Sleep(1000);
EventSetTimer(1);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
ObjectsDeleteAll(0,"Stocks");
EventKillTimer();
}
//+------------------------------------------------------------------+
//| Timer function |
//+------------------------------------------------------------------+
void OnTimer()
{
gdbBalance=inpBalanceCorrection;
gdbEquity=AccountInfoDouble(ACCOUNT_EQUITY);
stcDeal arrLostDeals[];
ArrayResize(arrLostDeals,11);
/**********************************************************************************
arrLostDeals[0].strSymbol="GOAU4F";
arrLostDeals[0].dtTime=D'2022.03.02 13:09:11';
arrLostDeals[0].enType=DEAL_TYPE_SELL;
arrLostDeals[0].dbVolume=9.0;
arrLostDeals[0].dbPrice=10.77;
arrLostDeals[1].strSymbol="GOAU4F";
arrLostDeals[1].dtTime=D'2022.03.03 00:00:00';
arrLostDeals[1].enType=DEAL_TYPE_SELL;
arrLostDeals[1].dbVolume=9.0;
arrLostDeals[1].dbPrice=11.29;
arrLostDeals[2].strSymbol="B3SA3F";
arrLostDeals[2].dtTime=D'2022.03.03 00:00:00';
arrLostDeals[2].enType=DEAL_TYPE_SELL;
arrLostDeals[2].dbVolume=9.0;
arrLostDeals[2].dbPrice=15.19;
arrLostDeals[3].strSymbol="B3SA3F";
arrLostDeals[3].dtTime=D'2022.03.03 00:00:01';
arrLostDeals[3].enType=DEAL_TYPE_BUY;
arrLostDeals[3].dbVolume=9.0;
arrLostDeals[3].dbPrice=14.73;
arrLostDeals[4].strSymbol="IRBR3F";
arrLostDeals[4].dtTime=D'2022.03.03 00:00:00';
arrLostDeals[4].enType=DEAL_TYPE_SELL;
arrLostDeals[4].dbVolume=30.0;
arrLostDeals[4].dbPrice=3.22;
arrLostDeals[5].strSymbol="ENJU3F";
arrLostDeals[5].dtTime=D'2022.03.03 14:54:40';
arrLostDeals[5].enType=DEAL_TYPE_BUY;
arrLostDeals[5].dbVolume=35.0;
arrLostDeals[5].dbPrice=2.9;
arrLostDeals[6].strSymbol="HASH11";
arrLostDeals[6].dtTime=D'2022.03.02 13:25:33';
arrLostDeals[6].enType=DEAL_TYPE_SELL;
arrLostDeals[6].dbVolume=3.0;
arrLostDeals[6].dbPrice=40.0;
arrLostDeals[7].strSymbol="HASH11";
arrLostDeals[7].dtTime=D'2022.03.02 13:25:33';
arrLostDeals[7].enType=DEAL_TYPE_SELL;
arrLostDeals[7].dbVolume=3.0;
arrLostDeals[7].dbPrice=40.0;
arrLostDeals[8].strSymbol="HASH11";
arrLostDeals[8].dtTime=D'2022.03.03 16:26:05';
arrLostDeals[8].enType=DEAL_TYPE_BUY;
arrLostDeals[8].dbVolume=3.0;
arrLostDeals[8].dbPrice=37.25;
arrLostDeals[9].strSymbol="CMIN3F";
arrLostDeals[9].dtTime=D'2022.03.02 13:01:13';
arrLostDeals[9].enType=DEAL_TYPE_SELL;
arrLostDeals[9].dbVolume=15.0;
arrLostDeals[9].dbPrice=6.38;
arrLostDeals[10].strSymbol="CMIN3F";
arrLostDeals[10].dtTime=D'2022.03.03 13:01:13';
arrLostDeals[10].enType=DEAL_TYPE_SELL;
arrLostDeals[10].dbVolume=15.0;
arrLostDeals[10].dbPrice=6.69;
********************************************************************************************/
strComment="";
double dbExposure=0.0;
ulong ulPositionTicket=0;
for(int i=0;i<PositionsTotal();i++)
{
ulPositionTicket=PositionGetTicket(i);
dbExposure+=PositionGetDouble(POSITION_PRICE_OPEN)*PositionGetDouble(POSITION_VOLUME);
}
MqlRates arrMqlRatesPositions[];
stcDeal dealLast;ZeroMemory(dealLast);
double dbPortfolioReturn=0.0;
double dbPortfolioRisk=0.0;
ulPositionTicket=0;
for(int i=0;i<PositionsTotal();i++)
{
ulPositionTicket=PositionGetTicket(i);
//--Retorno Médio
CopyRates(PositionGetSymbol(i),PERIOD_D1,0,(int)inpRatesQuantidade,arrMqlRatesPositions);
double dbRetornoMedia=0.0;
for(int j=0;j<ArraySize(arrMqlRatesPositions);j++) if(j>0) dbRetornoMedia+=(arrMqlRatesPositions[j].close-arrMqlRatesPositions[j-1].close)/(2/(1/(arrMqlRatesPositions[j].close)+(1/arrMqlRatesPositions[j-1].close)));
dbRetornoMedia=dbRetornoMedia/(ArraySize(arrMqlRatesPositions)-1);
dbPortfolioReturn+=dbRetornoMedia*PositionGetDouble(POSITION_VOLUME)*PositionGetDouble(POSITION_PRICE_OPEN)/gdbBalance;
//---> Variância
double dbRetornoVariancia=0.0;
for(int j=0;j<ArraySize(arrMqlRatesPositions);j++) if(j>0) dbRetornoVariancia+=MathPow(((arrMqlRatesPositions[j].close-arrMqlRatesPositions[j-1].close)/(2/(1/arrMqlRatesPositions[j].close+1/arrMqlRatesPositions[j-1].close)-dbRetornoMedia)),2);
dbRetornoVariancia=dbRetornoVariancia/(ArraySize(arrMqlRatesPositions)-1);
dbPortfolioRisk+=(dbRetornoVariancia)*MathPow(PositionGetDouble(POSITION_VOLUME)*PositionGetDouble(POSITION_PRICE_OPEN)/gdbBalance,2);
}
MqlRates arrMqlRatesSymbol[];
CopyRates(_Symbol,PERIOD_D1,0,(int)inpRatesQuantidade,arrMqlRatesSymbol);
double dbSymbol_r=0.0;
for(int i=0;i<ArraySize(arrMqlRatesSymbol);i++)if(i>0)dbSymbol_r+=(arrMqlRatesSymbol[i].close-arrMqlRatesSymbol[i-1].close)/(2/(1/(arrMqlRatesSymbol[i].close)+(1/arrMqlRatesSymbol[i-1].close)));
dbSymbol_r=dbSymbol_r/(ArraySize(arrMqlRatesSymbol)-1);
double dbSymbol_s=0.0;
for(int i=0;i<ArraySize(arrMqlRatesSymbol);i++)if(i>0)dbSymbol_s+=MathPow(((arrMqlRatesSymbol[i].close-arrMqlRatesSymbol[i-1].close)/(2/(1/arrMqlRatesSymbol[i].close+1/arrMqlRatesSymbol[i-1].close)-dbSymbol_r)),2);
dbSymbol_s=dbSymbol_s/(ArraySize(arrMqlRatesSymbol)-1);
stcDeal arrHistoryDeals[];
ZeroMemory(arrHistoryDeals);
int p=0;
int pos_l=0;
HistorySelect(0,TimeCurrent());
ulong ulHistoryDealTicket=0;
for(int i=0;i<HistoryDealsTotal();i++)
{
ulHistoryDealTicket=HistoryDealGetTicket(i);
if(HistoryDealGetString(ulHistoryDealTicket,DEAL_SYMBOL)==_Symbol)
{
ArrayResize(arrHistoryDeals,ArraySize(arrHistoryDeals)+1);
p=ArraySize(arrHistoryDeals);p--;
arrHistoryDeals[p].lPositionID=HistoryDealGetInteger(ulHistoryDealTicket,DEAL_POSITION_ID);
arrHistoryDeals[p].strSymbol=HistoryDealGetString(ulHistoryDealTicket,DEAL_SYMBOL);
arrHistoryDeals[p].enType=(ENUM_DEAL_TYPE)HistoryDealGetInteger(ulHistoryDealTicket,DEAL_TYPE);
arrHistoryDeals[p].dtTime=HistoryDealGetInteger(ulHistoryDealTicket,DEAL_TIME);
arrHistoryDeals[p].dbVolume=HistoryDealGetDouble(ulHistoryDealTicket,DEAL_VOLUME);
arrHistoryDeals[p].dbPrice=HistoryDealGetDouble(ulHistoryDealTicket,DEAL_PRICE);
if(ArraySize(arrLostDeals)>0)
{
for(int l=pos_l;l<ArraySize(arrLostDeals);l++)
{
if(arrLostDeals[l].strSymbol==_Symbol)
{
if(arrLostDeals[l].dtTime<arrHistoryDeals[p].dtTime)
{
arrHistoryDeals[p].lPositionID=0;
arrHistoryDeals[p].strSymbol=arrLostDeals[l].strSymbol;
arrHistoryDeals[p].enType=arrLostDeals[l].enType;
arrHistoryDeals[p].dtTime=arrLostDeals[l].dtTime;
arrHistoryDeals[p].dbVolume=arrLostDeals[l].dbVolume;
arrHistoryDeals[p].dbPrice=arrLostDeals[l].dbPrice;
pos_l=l+1; i--;
break;
}
}
}
}
}
}
strComment+="\n";
strComment+=StringFormat("Portfolio: Balance=%.2f, r=%.2f%%, s=%.2f%%, ld=%.2f%%, dn=%.2f%%\nSymbol: r=%.2f%%, s=%.2f%%, cv=%.5f, vol=%.0f, w=%.2f%%\n",
gdbBalance,
100*dbPortfolioReturn,
100*MathSqrt(dbPortfolioRisk),
100*dbExposure/gdbBalance,
100*(gdbBalance-gdbEquity)/gdbBalance,
100*dbSymbol_r,
100*MathSqrt(dbSymbol_s),
MathSqrt(dbSymbol_s)/dbSymbol_r,
MathRound(inpFinancialTicket/SymbolPrice(_Symbol,inpCalcMode)),
100*(MathRound(inpFinancialTicket/SymbolPrice(_Symbol,inpCalcMode))*(arrHistoryDeals.Size()>0?arrHistoryDeals[arrHistoryDeals.Size()-1].dbPrice:SymbolPrice(_Symbol,inpCalcMode)))/gdbBalance
);
p=0;
double dbPositionVolume=0.0;
stcDeal arrSymbolPositions[];
for(int i=0;i<ArraySize(arrHistoryDeals);i++)
{
if(arrHistoryDeals[i].enType==DEAL_TYPE_BUY){dbPositionVolume+=arrHistoryDeals[i].dbVolume;}
if(arrHistoryDeals[i].enType==DEAL_TYPE_SELL){dbPositionVolume-=arrHistoryDeals[i].dbVolume;}
if(dbPositionVolume==0.0){ArrayResize(arrSymbolPositions,0);}
else
{
ArrayResize(arrSymbolPositions,ArraySize(arrSymbolPositions)+1);
p=ArraySize(arrSymbolPositions);p--;
arrSymbolPositions[p].lPositionID=arrHistoryDeals[i].lPositionID;
arrSymbolPositions[p].strSymbol=arrHistoryDeals[i].strSymbol;
arrSymbolPositions[p].enType=arrHistoryDeals[i].enType;
arrSymbolPositions[p].dtTime=arrHistoryDeals[i].dtTime;
arrSymbolPositions[p].dbVolume=arrHistoryDeals[i].dbVolume;
arrSymbolPositions[p].dbPrice=arrHistoryDeals[i].dbPrice;
}
}
strComment+="\n";
double dbGridBasePrice=0.0;
if((ArraySize(arrHistoryDeals)>0)&&(inpLastPriceToBase)){dbGridBasePrice=arrHistoryDeals[0].dbPrice;}else{dbGridBasePrice=SymbolPrice(_Symbol,inpCalcMode);};
p=ArraySize(arrHistoryDeals)-1-ArraySize(arrSymbolPositions);
if(p>=0)
{
strComment+=StringFormat("%2s %s %s %s %6.2f %3.0f",
"L", //(int)i+1,
arrHistoryDeals[p].strSymbol,
StringSubstr(EnumToString((ENUM_DEAL_TYPE)arrHistoryDeals[p].enType),10,5),
TimeToString(arrHistoryDeals[p].dtTime,TIME_DATE|TIME_MINUTES|TIME_SECONDS),
arrHistoryDeals[p].dbPrice,
arrHistoryDeals[p].dbVolume
);
dbGridBasePrice=arrHistoryDeals[(arrHistoryDeals.Size()>=3?2:1)].dbPrice;
strComment+="\n";
}
double dbExcessReturn=0.0;
double dbExposureVolume=0.0;
for(int i=0;i<ArraySize(arrSymbolPositions);i++)
{
if(arrSymbolPositions[i].enType==DEAL_TYPE_BUY){dbExposureVolume+=arrSymbolPositions[i].dbVolume;}
if(arrSymbolPositions[i].enType==DEAL_TYPE_SELL){dbExposureVolume-=arrSymbolPositions[i].dbVolume;}
strComment+=StringFormat("%2.0f %s %s %s %6.2f %3.0f %4.0f",
(int)i+1,
arrSymbolPositions[i].strSymbol,
StringSubstr(EnumToString((ENUM_DEAL_TYPE)arrSymbolPositions[i].enType),10,5),
TimeToString(arrSymbolPositions[i].dtTime,TIME_DATE|TIME_MINUTES|TIME_SECONDS),
arrSymbolPositions[i].dbPrice,
arrSymbolPositions[i].dbVolume,
dbExposureVolume
);
if(ArraySize(arrHistoryDeals)>ArraySize(arrSymbolPositions))
if(i==0)
{
dbExcessReturn=100*(arrHistoryDeals[p].dbPrice-arrSymbolPositions[i].dbPrice)/(2/(1/arrHistoryDeals[p].dbPrice+1/arrSymbolPositions[i].dbPrice));
strComment+=StringFormat(" %5.2f%%",
dbExcessReturn
);
}
strComment+="\n";
}
double dbMax=0.0;
double dbMin=99999.99;
stcDeal dealSimulation; ZeroMemory(dealSimulation);
if(ArraySize(arrHistoryDeals)>0)
{
dealSimulation.strSymbol=arrHistoryDeals[ArraySize(arrHistoryDeals)-1].strSymbol;
dealSimulation.dbPrice=SymbolPrice(dealSimulation.strSymbol,inpCalcMode);
dealSimulation.dbVolume=(ArraySize(arrHistoryDeals)>0?arrHistoryDeals[ArraySize(arrHistoryDeals)-1].dbVolume:MathRound(inpFinancialTicket/SymbolPrice(_Symbol,inpCalcMode)));
if(arrHistoryDeals[ArraySize(arrHistoryDeals)-1].enType==DEAL_TYPE_BUY)if(SymbolPrice(dealSimulation.strSymbol,inpCalcMode)>arrHistoryDeals[ArraySize(arrHistoryDeals)-1].dbPrice){dealSimulation.enType=(ENUM_DEAL_TYPE)DEAL_TYPE_SELL;ObjectCreate(0,"Stocks_SimulationSell",OBJ_ARROW_DOWN,0,TimeLocal(),arrHistoryDeals[ArraySize(arrHistoryDeals)-1].dbPrice/(1-(arrHistoryDeals[ArraySize(arrHistoryDeals)-1].dbPrice*dealSimulation.dbVolume)/gdbBalance));ObjectSetInteger(0,"Stocks_SimulationSell",OBJPROP_COLOR,clrRed);}
if(arrHistoryDeals[ArraySize(arrHistoryDeals)-1].enType==DEAL_TYPE_BUY)if(SymbolPrice(dealSimulation.strSymbol,inpCalcMode)<=arrHistoryDeals[ArraySize(arrHistoryDeals)-1].dbPrice){dealSimulation.enType=(ENUM_DEAL_TYPE)DEAL_TYPE_BUY;ObjectCreate(0,"Stocks_SimulationBuy",OBJ_ARROW_UP,0,TimeLocal(),arrHistoryDeals[ArraySize(arrHistoryDeals)-1].dbPrice*(1-(arrHistoryDeals[ArraySize(arrHistoryDeals)-1].dbPrice*dealSimulation.dbVolume)/gdbBalance));ObjectSetInteger(0,"Stocks_SimulationBuy",OBJPROP_COLOR,clrBlue);}
if(arrHistoryDeals[ArraySize(arrHistoryDeals)-1].enType==DEAL_TYPE_SELL)if(SymbolPrice(dealSimulation.strSymbol,inpCalcMode)>arrHistoryDeals[ArraySize(arrHistoryDeals)-1].dbPrice)
if(dbExposureVolume>0.0){dealSimulation.enType=(ENUM_DEAL_TYPE)DEAL_TYPE_SELL;ObjectCreate(0,"Stocks_SimulationSell",OBJ_HLINE,0,0,arrHistoryDeals[ArraySize(arrHistoryDeals)-1].dbPrice/(1-(arrHistoryDeals[ArraySize(arrHistoryDeals)-1].dbPrice*dealSimulation.dbVolume)/gdbBalance));ObjectSetInteger(0,"Stocks_SimulationSell",OBJPROP_STYLE,STYLE_DASHDOT);ObjectSetInteger(0,"Stocks_SimulationSell",OBJPROP_COLOR,clrFireBrick);}
else{dealSimulation.enType=(ENUM_DEAL_TYPE)DEAL_TYPE_BUY;ObjectCreate(0,"Stocks_SimulationBuy",OBJ_HLINE,0,0,arrHistoryDeals[ArraySize(arrHistoryDeals)-1].dbPrice*(1-(arrHistoryDeals[ArraySize(arrHistoryDeals)-1].dbPrice*dealSimulation.dbVolume)/gdbBalance));ObjectSetInteger(0,"Stocks_SimulationBuy",OBJPROP_STYLE,STYLE_DASHDOT);ObjectSetInteger(0,"Stocks_SimulationBuy",OBJPROP_COLOR,clrMidnightBlue);}
if(arrHistoryDeals[ArraySize(arrHistoryDeals)-1].enType==DEAL_TYPE_SELL)if(SymbolPrice(dealSimulation.strSymbol,inpCalcMode)<=arrHistoryDeals[ArraySize(arrHistoryDeals)-1].dbPrice){dealSimulation.enType=(ENUM_DEAL_TYPE)DEAL_TYPE_BUY;ObjectCreate(0,"Stocks_SimulationBuy",OBJ_HLINE,0,0,arrHistoryDeals[ArraySize(arrHistoryDeals)-1].dbPrice*(1-(arrHistoryDeals[ArraySize(arrHistoryDeals)-1].dbPrice*dealSimulation.dbVolume)/gdbBalance));ObjectSetInteger(0,"Stocks_SimulationBuy",OBJPROP_STYLE,STYLE_DASHDOT);ObjectSetInteger(0,"Stocks_SimulationBuy",OBJPROP_COLOR,clrMidnightBlue);}
strComment+=StringFormat("%2s %s %s %s %6.2f %3.0f %4.0f %5.2f%%\n",
"S", //(int)i+1,
dealSimulation.strSymbol,
StringSubstr(EnumToString((ENUM_DEAL_TYPE)dealSimulation.enType),10,5),
TimeToString(TimeLocal(),TIME_DATE|TIME_MINUTES|TIME_SECONDS),
dealSimulation.dbPrice,
dealSimulation.dbVolume,
(dealSimulation.enType==DEAL_TYPE_BUY?dbExposureVolume+dealSimulation.dbVolume:dbExposureVolume-dealSimulation.dbVolume),
100*(dealSimulation.enType==DEAL_TYPE_BUY?(arrHistoryDeals[ArraySize(arrHistoryDeals)-1].dbPrice-dealSimulation.dbPrice)/(2/(1/dealSimulation.dbPrice+1/arrHistoryDeals[ArraySize(arrHistoryDeals)-1].dbPrice)):(dealSimulation.dbPrice-arrHistoryDeals[ArraySize(arrHistoryDeals)-1].dbPrice)/(2/(1/dealSimulation.dbPrice+1/arrHistoryDeals[ArraySize(arrHistoryDeals)-1].dbPrice)))
);
double dbVWAP=0.0;
ulong iTickCount=0;
double dbSumVolum=0;
MqlTick arrMqlTicks[];
CopyTicks(_Symbol,arrMqlTicks,COPY_TICKS_TRADE,(ulong)(TimeCurrent()-(inpRatesQuantidade*86400))*1000,(uint)TimeCurrent());
for(int i=0;i<ArraySize(arrMqlTicks);i++)
if(arrMqlTicks[i].last>0)
{
dbMax=MathMax(dbMax,arrMqlTicks[i].last);
dbMin=MathMin(dbMin,arrMqlTicks[i].last);
dbVWAP+=arrMqlTicks[i].last*arrMqlTicks[i].volume_real;
dbSumVolum+=arrMqlTicks[i].volume_real;
iTickCount++;
}
dbVWAP=dbVWAP/dbSumVolum;
double dbMedian=0.0;
double arrPrecos[];
ArrayResize(arrPrecos,ArraySize(arrMqlTicks));
for(int i=0;i<ArraySize(arrMqlTicks);i++) arrPrecos[i]=arrMqlTicks[i].last;
ArraySort(arrPrecos);
dbMedian=(ArraySize(arrPrecos)>0?arrPrecos[ArraySize(arrPrecos)/2]:0.0);
//strComment+=StringFormat("\nmáx=%.2f (%.2f%%)\nmed=%.2f (%.2f%%), vwap=%.2f (%.2f%%)\nmín=%.2f (%.2f%%)\n",
// dbMax,
// 100*(dbMax-SymbolPrice(_Symbol,inpCalcMode))/(2/(1/dbMax+1/SymbolPrice(_Symbol,inpCalcMode))),
// dbMedian,
// 100*(dbMedian-SymbolPrice(_Symbol,inpCalcMode))/(2/(1/dbMedian+1/SymbolPrice(_Symbol,inpCalcMode))),
// dbVWAP,
// 100*(dbVWAP-SymbolPrice(_Symbol,inpCalcMode))/(2/(1/dbVWAP+1/SymbolPrice(_Symbol,inpCalcMode))),
// dbMin,
// 100*(dbMin-SymbolPrice(_Symbol,inpCalcMode))/(2/(1/dbMin+1/SymbolPrice(_Symbol,inpCalcMode)))
//);
//ObjectCreate(0,"Stocks_SymbolVWAP",OBJ_HLINE,0,0,dbVWAP);ObjectSetInteger(0,"Stocks_SymbolVWAP",OBJPROP_STYLE,STYLE_DOT);ObjectSetInteger(0,"Stocks_SymbolVWAP",OBJPROP_COLOR,clrDarkKhaki);
//ObjectCreate(0,"Stocks_SymbolMin",OBJ_HLINE,0,0,dbMin);ObjectSetInteger(0,"Stocks_SymbolMin",OBJPROP_STYLE,STYLE_DOT);ObjectSetInteger(0,"Stocks_SymbolMin",OBJPROP_COLOR,clrDarkBlue);
//ObjectCreate(0,"Stocks_SymbolMax",OBJ_HLINE,0,0,dbMax);ObjectSetInteger(0,"Stocks_SymbolMax",OBJPROP_STYLE,STYLE_DOT);ObjectSetInteger(0,"Stocks_SymbolMax",OBJPROP_COLOR,clrFireBrick);
//strComment+=StringFormat("Impact: d_r=%.4f%%, d_s=%.4f%%, n_ld=%.2f%%",
// 100*((dbPortfolioReturn+((dbSymbol_r*(MathRound(inpFinancialTicket/SymbolPrice(_Symbol,inpCalcMode)))*SymbolPrice(_Symbol,inpCalcMode))/gdbBalance))-dbPortfolioReturn),
// 100*MathSqrt(dbPortfolioRisk+(dbSymbol_s*(MathPow(MathRound(inpFinancialTicket/SymbolPrice(_Symbol,inpCalcMode))*SymbolPrice(_Symbol,inpCalcMode)/gdbBalance,2))))-(MathSqrt(dbPortfolioRisk)*100),
// 100*((dbExposure+(MathRound(inpFinancialTicket/SymbolPrice(_Symbol,inpCalcMode))*SymbolPrice(_Symbol,inpCalcMode)))/gdbBalance)
//);
}
else
{
double dbVWAP=0.0;
ulong iTickCount=0;
double dbSumVolum=0;
MqlTick arrMqlTicks[];
CopyTicks(_Symbol,arrMqlTicks,COPY_TICKS_TRADE,(ulong)(TimeCurrent()-(inpRatesQuantidade*86400))*1000,(uint)TimeCurrent());
for(int i=0;i<ArraySize(arrMqlTicks);i++)
if(arrMqlTicks[i].last>0)
{
dbMax=MathMax(dbMax,arrMqlTicks[i].last);
dbMin=MathMin(dbMin,arrMqlTicks[i].last);
dbVWAP+=arrMqlTicks[i].last*arrMqlTicks[i].volume_real;
dbSumVolum+=arrMqlTicks[i].volume_real;
iTickCount++;
}
dbVWAP=dbVWAP/dbSumVolum;
double dbMedian=0.0;
double arrPrecos[];
ArrayResize(arrPrecos,ArraySize(arrMqlTicks));
for(int i=0;i<ArraySize(arrMqlTicks);i++) arrPrecos[i]=arrMqlTicks[i].last;
ArraySort(arrPrecos);
dbMedian=(ArraySize(arrPrecos)>0?arrPrecos[ArraySize(arrPrecos)/2]:0.0);
//strComment+=StringFormat("\nmáx=%.2f (%.2f%%)\nmed=%.2f (%.2f%%), vwap=%.2f (%.2f%%)\nmín=%.2f (%.2f%%)\n",
// dbMax,
// 100*(dbMax-SymbolPrice(_Symbol,inpCalcMode))/(2/(1/dbMax+1/SymbolPrice(_Symbol,inpCalcMode))),
// dbMedian,
// 100*(dbMedian-SymbolPrice(_Symbol,inpCalcMode))/(2/(1/dbMedian+1/SymbolPrice(_Symbol,inpCalcMode))),
// dbVWAP,
// 100*(dbVWAP-SymbolPrice(_Symbol,inpCalcMode))/(2/(1/dbVWAP+1/SymbolPrice(_Symbol,inpCalcMode))),
// dbMin,
// 100*(dbMin-SymbolPrice(_Symbol,inpCalcMode))/(2/(1/dbMin+1/SymbolPrice(_Symbol,inpCalcMode)))
//);
//ObjectCreate(0,"Stocks_SymbolVWAP",OBJ_HLINE,0,0,dbVWAP);ObjectSetInteger(0,"Stocks_SymbolVWAP",OBJPROP_STYLE,STYLE_DOT);ObjectSetInteger(0,"Stocks_SymbolVWAP",OBJPROP_COLOR,clrDarkKhaki);
}
ObjectCreate(0,"Stocks_SymbolPrice",OBJ_HLINE,0,0,SymbolPrice(_Symbol,inpCalcMode));ObjectSetInteger(0,"Stocks_SymbolPrice",OBJPROP_STYLE,STYLE_SOLID);ObjectSetInteger(0,"Stocks_SymbolPrice",OBJPROP_COLOR,clrYellow);
//strComment+="\n";
if(inpGrid)
{
double dbGridLowerLimit=0.0;
switch(inpGridLowerType)
{
case MinHistoric:
{
dbGridLowerLimit=9999.99;
MqlRates arrMqlRatesGrid[];
CopyRates(_Symbol,PERIOD_D1,0,999999999,arrMqlRatesGrid);
for(int i=0;i<ArraySize(arrMqlRatesGrid);i++)
{
if(dbGridLowerLimit>arrMqlRatesGrid[i].low) dbGridLowerLimit=arrMqlRatesGrid[i].low;
}
break;
}
case MinHistoric_Minus50pcToZero:
{
dbGridLowerLimit=9999.99;
MqlRates arrMqlRatesGrid[];
CopyRates(_Symbol,PERIOD_D1,0,999999999,arrMqlRatesGrid);
for(int i=0;i<ArraySize(arrMqlRatesGrid);i++)
{
if(dbGridLowerLimit>arrMqlRatesGrid[i].low) dbGridLowerLimit=arrMqlRatesGrid[i].low;
}
dbGridLowerLimit-=(dbGridLowerLimit/2);
break;
}
case One_Mili:
dbGridLowerLimit=0.001;
break;
case One_Cents:
dbGridLowerLimit=0.01;
break;
case Two_Half_Cents:
dbGridLowerLimit=0.025;
break;
case Ten_Cents:
dbGridLowerLimit=0.1;
break;
case One_Money:
dbGridLowerLimit=1.0;
break;
default:
dbGridLowerLimit=inpGridLowerLimit;
}
ObjectsDeleteAll(ChartID(),"Stocks_Grid");
string strGridObjectName="";
double dbGridVolume=(inpGridVolume>0.0?inpGridVolume:(ArraySize(arrHistoryDeals)>0?arrHistoryDeals[0].dbVolume:MathRound(inpFinancialTicket/SymbolPrice(_Symbol,inpCalcMode))));
dbGridVolume=(inpGridSec>0.0?dbGridVolume/inpGridSec:SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN));
double dbGridExposureVolume=0.0;
double dbGridExposure=0.0;
for(double i=dbGridBasePrice;i<(dbGridBasePrice*10.0);i+=(i*((dbGridVolume*dbGridBasePrice)/gdbBalance)))
{
strGridObjectName=StringFormat("Stocks_Grid_p%.2f_v%.0f",NormalizeDouble(i,2),dbGridVolume);
ObjectCreate(0,strGridObjectName,OBJ_HLINE,0,0,i);
ObjectSetInteger(0,strGridObjectName,OBJPROP_STYLE,STYLE_DASHDOT);
ObjectSetInteger(0,strGridObjectName,OBJPROP_COLOR,clrDimGray);
ObjectSetInteger(0,strGridObjectName,OBJPROP_BACK,1);
}
for(double i=dbGridBasePrice;i>=dbGridLowerLimit;i-=(i*((dbGridVolume*dbGridBasePrice)/gdbBalance)))
{
strGridObjectName=StringFormat("Stocks_Grid_p%.2f_v%.0f",NormalizeDouble(i,2),dbGridVolume);
ObjectCreate(0,strGridObjectName,OBJ_HLINE,0,0,i);
ObjectSetInteger(0,strGridObjectName,OBJPROP_STYLE,STYLE_DASHDOT);
ObjectSetInteger(0,strGridObjectName,OBJPROP_COLOR,clrDimGray);
ObjectSetInteger(0,strGridObjectName,OBJPROP_BACK,1);
dbGridExposure+=dbGridVolume*i;
dbGridExposureVolume+=dbGridVolume;
}
//strComment+="GRID:";
//strComment+=StringFormat("\nbase=%.2f, lim_low=%.4f, v=%.0f\nv_max=%.0f, ld_max=%.2f%%",
// dbGridBasePrice,
// dbGridLowerLimit,
// dbGridVolume,
// dbGridExposureVolume,
// 100*dbGridExposure/gdbBalance
//);
if(dbGridExposure>gdbBalance){strComment+=" [ FAIL !!! ]";ObjectsDeleteAll(ChartID(),"Stocks_Grid");};
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------Best Deal
stcDeal bestDeal;
ZeroMemory(bestDeal);
string strSymbol="";
double dbYield=0.0;
double dbPreviousYield=-9999.0;
for(int i=0;i<SymbolsTotal(true);i++)
{
strSymbol=SymbolName(i,true);
if(
(SymbolInfoDouble(strSymbol,SYMBOL_ASK)>0.0)
&&(SymbolInfoDouble(strSymbol,SYMBOL_BID)>0.0)
)
{
stcDeal lastDeal = getLastDeal(strSymbol);
if(lastDeal.dbPrice>0.0)
{
if(lastDeal.enType==DEAL_TYPE_SELL)
{
dbYield=(lastDeal.dbPrice-SymbolPrice(strSymbol,inpCalcMode))/(2/(1/lastDeal.dbPrice+1/SymbolInfoDouble(strSymbol,SYMBOL_BID)));
}
else
{
dbYield=(SymbolPrice(strSymbol,inpCalcMode)-lastDeal.dbPrice)/(2/(1/lastDeal.dbPrice+1/SymbolInfoDouble(strSymbol,SYMBOL_ASK)));
}
if(dbPreviousYield<=dbYield)
{
dbPreviousYield=dbYield;
bestDeal.strSymbol=strSymbol;
bestDeal.dbYield=dbPreviousYield;
if(lastDeal.enType==DEAL_TYPE_SELL)
{
bestDeal.enType=DEAL_TYPE_BUY;
bestDeal.dbPrice=SymbolInfoDouble(bestDeal.strSymbol,SYMBOL_ASK);
bestDeal.dbVolume=lastDeal.dbVolume;
}
else
{
bestDeal.enType=DEAL_TYPE_SELL;
bestDeal.dbPrice=SymbolInfoDouble(bestDeal.strSymbol,SYMBOL_BID);
bestDeal.dbVolume=MathRound(inpFinancialTicket/bestDeal.dbPrice);
}
}
}
}
}
if(
(StringLen(bestDeal.strSymbol)>0)
)
{
if(inpLoadGraph) ChartSetSymbolPeriod(ChartID(),bestDeal.strSymbol,ChartPeriod(0));
strComment+=StringFormat("\n%s %.0f %s %.2f (%.2f%%)",
StringSubstr(EnumToString((ENUM_DEAL_TYPE)bestDeal.enType),10,4),
bestDeal.dbVolume,
bestDeal.strSymbol,
bestDeal.dbPrice,
100*bestDeal.dbYield
);
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------Best Deak (End)
for(int i=0;i<PositionsTotal();i++)
{
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------Send Orders (End)
Comment(strComment);
}
//+------------------------------------------------------------------+
//| Ativo subjacente da opção |
//+------------------------------------------------------------------+
double SymbolPrice(const string SYMBOL, const CalcMode CALCMODE)
{
double result = 0.0;
switch(CALCMODE)
{
case Last:
return(SymbolInfoDouble(SYMBOL,SYMBOL_LAST));
break;
case VWAP:
return(SymbolInfoDouble(SYMBOL,SYMBOL_SESSION_AW));
break;
case Median:
return(TrueMedian(SymbolInfoDouble(SYMBOL,SYMBOL_BID),SymbolInfoDouble(SYMBOL,SYMBOL_ASK),SymbolInfoDouble(SYMBOL,SYMBOL_LAST)));
break;
case AskBidWatch:
return(SymbolInfoDouble(SYMBOL,SYMBOL_ASK)+SymbolInfoDouble(SYMBOL,SYMBOL_BID))/2;
break;
}
return(result);
}
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)));
}
//+------------------------------------------------------------------+
//| Last Deal |
//+------------------------------------------------------------------+
stcDeal getLastDeal(const string strSymbol)
{
stcDeal dealLast;
ZeroMemory( dealLast );
ulong uTicket;
HistorySelect(0,TimeCurrent());
for(int i=0;i<(HistoryDealsTotal());i++)
{
uTicket=HistoryDealGetTicket(i);
if(HistoryDealGetString(uTicket,DEAL_SYMBOL)==strSymbol)
{
dealLast.enType=(ENUM_DEAL_TYPE)HistoryDealGetInteger(uTicket,DEAL_TYPE);
dealLast.strSymbol=HistoryDealGetString(uTicket,DEAL_SYMBOL);
dealLast.dbVolume=HistoryDealGetDouble(uTicket,DEAL_VOLUME);
dealLast.dbPrice=HistoryDealGetDouble(uTicket,DEAL_PRICE);
}
}
return( dealLast );
}
//+------------------------------------------------------------------+