Biblioteca2/Avalon_2refs_multi.mq5
super.admin 464d030eb2 convert
2025-05-30 14:43:36 +02:00

887 lines
83 KiB
MQL5

#property copyright "Rafael Morgado Silva"
#property link ""
#property version "1.00"
#include <Math\Stat\Math.mqh>
#include <Trade\Trade.mqh>
#include "Include\defs.mqh"//definições gerais, parâmetros gerais
#include "Include\locks.mqh"//travas
#include "Include\manage.mqh"//gerenciaento de ordens/posições
#include "Include\stops.mqh"//Stop loss e take profit
#include "Include\strategy.mqh"//estratégias
#include "Include\filters.mqh"//filtros
struct MyData//Callback com a estrutura de dados do robô
{
CLock* Lock;
PLock* PosLock;
ALock* AssetLock;
Signal* StrategyB1;
Signal* StrategyB2;
Signal* StrategyS1;
Signal* StrategyS2;
Filters* Liquidity;
Filters* PriceMin;
OrderData* PosData;
void operator=(const MyData &r)
{
Lock=r.Lock;
PosLock=r.PosLock;
AssetLock=r.AssetLock;
StrategyB1=r.StrategyB1;
StrategyB2=r.StrategyB2;
StrategyS1=r.StrategyS1;
StrategyS2=r.StrategyS2;
Liquidity=r.Liquidity;
PriceMin=r.PriceMin;
PosData=r.PosData;
}
};
#include "Include\ranking.mqh"//tabela, ordenamento, ranking
#include "Include\money.mqh"//gerenciamento de saldo, margem, etc
//#include <report.mqh>//para gerar o relatório personalizado em pdf
#include "Include\data.mqh"
#include "Include\report.mqh"
//#include <Graphics\Graphic.mqh>
input string LineE11="-----------------------Parâmetros Estratégia 1 ------------------";
input MODEL_TYPES E1ModelType=Tendencia;//Tipo de modelo
input ENUM_TIMEFRAMES E1TimeFrameB=PERIOD_M15;//Timeframe ATR compra
input int E1PAtrB=21;//Período do ATR compra
input ENUM_TIMEFRAMES E1TimeFrameS=PERIOD_M15;//Timeframe ATR venda
input int E1PAtrS=21;//Período do ATR venda
input REF_TYPES E1Type=Ref_price_maxmin;//Tipo de estratégia
input REF_PRICES_TYPES E1Price=Ref_pt_maxmin;//Tipo de preço
input int E1Periodo=7;//Número de barras no sinal
input ENUM_TIMEFRAMES E1RefTimeFrame=PERIOD_M5;//Timeframe da referência
input double E1AtrFrac=0.0;//Fração do Atr de deslocamento
input bool E1ConfCandle=false;//Usar candle de confirmação do rompimento
input string python_fname="";//Nome do script python
input bool UsePythonTicker=true;//Usar o ticker do script python
input bool UsePythonVolume=true;//Usar o volume do script python
input string LineE12="----------------------------------------------------------";
input string E21="-----------------------Parâmetros Estratégia 2 ------------------";
input MODEL_TYPES E2ModelType=Tendencia;//Tipo de modelo
input ENUM_TIMEFRAMES E2TimeFrameB=PERIOD_M15;//Timeframe ATR compra
input int E2PAtrB=21;//Período do ATR compra
input ENUM_TIMEFRAMES E2TimeFrameS=PERIOD_M15;//Timeframe ATR venda
input int E2PAtrS=21;//Período do ATR venda
input REF_TYPES E2Type=Ref_price_maxmin;//Tipo de estratégia
input REF_PRICES_TYPES E2Price=Ref_pt_maxmin;//Tipo de preço
input int E2Periodo=7;//Número de barras no sinal
input ENUM_TIMEFRAMES E2RefTimeFrame=PERIOD_M5;//Timeframe da referência
input double E2AtrFrac=0.0;//Fração do Atr de deslocamento
input bool E2ConfCandle=false;//Usar candle de confirmação do rompimento
input string E22="----------------------------------------------------------";
/*input string Shadow1="-----------------------Parâmetros shadow -----------------";
input bool AtrVar_shadow=false;//Usar janela variável com ATR
input bool SignalOrig_shadow=true;//Sinal original - lag preço/código - lag ssb
input string Shadow2="----------------------------------------------------------";
input string Elefante1="-----------------------Parâmetros Elefante -----------------";
input bool RRFilter_elefante=true;//Usar filtro de Retorno/Risco
input double RRFrac_elefante=0.33;//Fração RR
input bool SSBFilter_elefante=true;//Usar filtro SSB
input bool ConfCandle_elefante=true;//Usar candle de confirmação do rompimento
input bool SlOrig_elefante=false;//SL original - extensão acima(abaixo) pivô/ponto médio do elefante
input bool TpOrig_elefante=false;//TP original - extensão baixo(acima) pivô/extensão acima(abaixo) elefante
input bool PivotCandle_elefante=false;//Usar candle de pivot - rompimento do pivô/elefante
input bool BodyElefant_elefante=true;//Usar só o corpo do candle elefante
input bool BodyPivot_elefante=false;//Usar só o corpo do candle pivô
input string Elefante2="-------------------------------------------------------------";*/
input string Ft11="----------------Parâmetros Filtro 1 -----------------------";
input bool UseFilter1=false;//Habilitar filtro
input FILTER_TYPES MyFilter1=FTLiq;//Tipo de filtro
input double LiqFrac1=0.95;//Corte filtro de liquidez
input ENUM_TIMEFRAMES FTimeFrame1=PERIOD_D1;//Timeframe do filtro
input int FPeriod1=30;//Período do filtro
input string FSymbol1="IBOV";//Ativo referência para o filtro
input string Ft21="------------------------------------------------------------";
input string Ft12="----------------Parâmetros Filtro 2-------------------------";
input bool UseFilter2=false;//Habilitar filtro
input FILTER_TYPES MyFilter2=FTPre;//Tipo de filtro
input double PreMin2=4;//Preço mínimo
input string Ft22="------------------------------------------------------------";
input string T12="-----------------------Parâmetros da Tabela-------";
//input string TableFile="mlcx-09-12.txt";//Arquivo com os tickers
input Periodicity TablePeriodicity=Mes;//Periodicidade da tabela
input ENUM_TIMEFRAMES TableTimeframe=PERIOD_D1;//Timeframe da tabela
input int TablePeriod=120;//Janela da tabela
input ENUM_TIMEFRAMES TableAtrTimeframe=PERIOD_D1;//Timeframe do atr
input int TableAtrPeriod=21;//Janela do atr
input RankTypes MyRank=RTRent_atr;//Tipo de ordenamento
input RankSelectTypes MySelectionType=RSTAll;//Tipo de seleção
input int RSTFixedAssets=20;//Número de ativos (seleção fixa)
input bool UseRenorm=true;//Renormalizar a tabela
input bool UseTableLiqFilter=true;//Habilitar filtro de liquidez na tabela
//input double liqfrac=0.95;//Corte filtro de liquidez
//input int liqper=30;//Janela do filtro liquidez
//input ENUM_TIMEFRAMES liqtime=PERIOD_M5;//Timeframe do filtro de liquidez
//input string liqrefsymb="IBOV";//Ativo referência para o filtro de liquidez
input bool UseTablePreFilter=true;//Habilitar filtro de preço na tabela
input double premin=4;//Preço mínimo
input bool UseTableLowVolFilter=true;//Habilitar filtro somente positivos na tabela
input double Alavancagem=5;//Alavancagem
input bool UseRebal=false;//Usar algoritmo de rebalanço
input bool ChangeCapital=false;//Redimensionar a carteira atual, mudando o capital
input int THour=9;//Horário de cálculo da carteira
input int TMin=0;//Minuto de cálculo da carteira
input bool EnableMonteCarlo=false;//Habilitar Monte Carlo com a lista de ativos
input int NativosMonteCarlo=50;//Número de ativos por teste
input int SeedMonteCarlo=0;//Semente aleatória do teste
input string T22="---------------------------------------------------";
input string T23="---------------Neutralização-----------------------";
input bool UseNeutralization=false;//Habilita neutralização da carteira
input string NeutralAsset1="WDO$D";//Ativo neutralizador 1 (comprado)
input string NeutralAsset2="WIN$D";//Ativo neutralizador 2 (vendido)
input Neutralization_TYPES NeutralMethod=NTRisco;//Tipo de neutralização
input string T24="---------------------------------------------------";
input string M12="---------------Gerenciamento de Saldo--------------";
input bool MGMTMargin=true;//Usar limitação de margem
input ENUM_MONEY_MGMT MGMTType=MMTAccount;//Tipo de gerenciamento
input double mycapital=100000;//Capital (fixo)
input double mymargin=200000;//Margem (fixo)
input double mymarginfrac=2;//Margem em % do saldo (Saldo)
input string M22="---------------------------------------------------";
input string N12="---------------Telegram--------------";
input bool UseTelegram;//Habilitar bot no Telegram
input bool EqtyPlot=true;//Gráfico de saldo(T) ou investido(F)
input string N22="---------------------------------------------------";
CTrade Trade;
Table Assets;
MoneyMgmt Money;
MyTimer ThisTimer;
string MyName;
DataAquisition Metadata,Reportdata;
BotTelegram ThisBot;
string TelegramBuffer;
//bool TelegramSendLogs=false;
//long TelegramLogsIds[];
//Position MyPositions;
void OnTimer()
{
if ((!MQLInfoInteger(MQL_TESTER))&&(!MQLInfoInteger(MQL_OPTIMIZATION)))//online
{
double profit=0;
double f_profit=0;
for (int i=0;i<ArraySize(Assets.data);i++)
{
string ticker=Assets.data[i].ticker;
profit+=calc_profit(ticker,DEAL_TYPE_SELL);
profit+=calc_profit(ticker,DEAL_TYPE_BUY);
f_profit+=float_profit(ticker,POSITION_TYPE_BUY);
f_profit+=float_profit(ticker,POSITION_TYPE_SELL);
Assets.data[i].mydata.Lock.CheckLock(ticker,LockExp);
Assets.data[i].mydata.PosLock.CheckLock(ticker,LockExp);
}
Comment(TimeToString(TimeLocal(),TIME_DATE|TIME_SECONDS)+"\n"+
"Lucro realizado: "+DoubleToString(profit,2)+" "+DoubleToString(100.0*profit/Money.Balance(),2)+"%\n"
"Lucro flutuante: "+DoubleToString(f_profit,2)+" "+DoubleToString(100.0*f_profit/Money.Balance(),2)+"%\n");
/* MqlDateTime today;//Relatórios diários
TimeLocal(today);
if ((today.hour>=18)&&(today.min>=1)&&(today.day_of_week!=SATURDAY)&&(today.day_of_week!=SUNDAY))
{
if (FileIsExist(MyName+"-dailyreport.csv"))
{
MqlDateTime fdata;
TimeToStruct((datetime)FileGetInteger(MyName+"-dailyreport.csv",FILE_MODIFY_DATE),fdata);
if ((fdata.day!=today.day)||((fdata.day==today.day)&&(fdata.hour==18)&&(fdata.min<1))||((fdata.day==today.day)&&(fdata.hour<18)))
{
Metadata.FileToFile(MyName);//lê MyName+DataFname, salva MyName+"-dailyreport.csv"
ShellOpenFile(MyName+"-dailyreport.bat");//chama gnuplot MyName+"-daylyreport.gp"
if (UseTelegram)
{
Sleep(10*1000);
ThisBot.SendResult();
}
}
}
else
{
Metadata.FileToFile(MyName);//lê MyName+DataFname, salva MyName+"-dailyreport.csv"
ShellOpenFile(MyName+"-dailyreport.bat");//chama gnuplot MyName+"-daylyreport.gp"
if (UseTelegram)
{
Sleep(10*1000);
ThisBot.SendResult();
}
}
}*/
static int tlgrmcnt=0;
if (UseTelegram)
{
if (tlgrmcnt>15)
{
ThisBot.Update();
tlgrmcnt=0;
}
else tlgrmcnt++;
}
}
else if ((MQLInfoInteger(MQL_TESTER))&&(!MQLInfoInteger(MQL_OPTIMIZATION)))//tester
{
MqlDateTime today;
TimeLocal(today);
if ((today.hour>=19)&&(today.min>=0)) Reportdata.SaveToArray();
}
}
double OnTester()
{
if (MakePdf&&(MQLInfoInteger(MQL_TESTER))&&(!MQLInfoInteger(MQL_OPTIMIZATION)))//tester
{
Reportdata.ArrayToFile();
//RunGnuplot("plot.gp");
ShellOpenFile("report.bat");
// long chartid=ChartOpen("IBOV",PERIOD_D1);
// ChartSetInteger(chartid,CHART_SHOW,false);
// CGraphic graphic;
// graphic.Create(chartid,"Graphic",0,30,30,780,380);
// double x[]={-10,-4,-1,2,3,4,5,6,7,8};
// double y[]={-5,4,-10,23,17,18,-9,13,17,4};
// CCurve *curve=graphic.CurveAdd(x,y,CURVE_LINES);
// graphic.CurvePlotAll();
// graphic.Update();
// GraphPlot(x,y,CURVE_LINES);
//if (FileIsExist("report.pdf",FILE_COMMON)) FileDelete("report.pdf",FILE_COMMON);
//RunLatex("report.tex");
//while (!FileIsExist("report.pdf",FILE_COMMON)) Sleep(1000);
//ShellOpenFile("report.pdf");
}
return(100.0*TesterStatistics(STAT_BALANCE_DD)/TesterStatistics(STAT_INITIAL_DEPOSIT));
}
void OnDeinit(const int reason)
{
for (int i=0;i<ArraySize(Assets.data);i++)
{
if (UseBook) MarketBookRelease(Assets.data[i].ticker);
delete Assets.data[i].mydata.Lock;
delete Assets.data[i].mydata.PosLock;
delete Assets.data[i].mydata.AssetLock;
delete Assets.data[i].mydata.StrategyB1;
delete Assets.data[i].mydata.StrategyS1;
delete Assets.data[i].mydata.StrategyB2;
delete Assets.data[i].mydata.StrategyS2;
delete Assets.data[i].mydata.Liquidity;
delete Assets.data[i].mydata.PriceMin;
delete Assets.data[i].mydata.PosData;
}
EventKillTimer();
}
void OnBookEvent(const string& psymbol)
{
if (UseBook)
for (int i=0;i<ArraySize(Assets.data);i++)
if ((Assets.data[i].selected)&&//chama via onbookevent somente para os selecionados->economia de cpu
(Assets.data[i].ticker==psymbol))
ontick(Assets.data[i],Money.MarginFree(Assets.data));
return;
}
void OnTick()
{
if (SaveData)
{
Metadata.DataFname=TimeToString(TimeLocal(),TIME_DATE)+"-data.csv";
if (!FileIsExist(MyName+Metadata.DataFname))
{
int dataoutput=FileOpen(MyName+Metadata.DataFname,FILE_READ|FILE_WRITE|FILE_CSV|FILE_ANSI,';',CP_UTF8);
FileWrite(dataoutput,"Date",Metadata.SymbolRef,"Equity","Balance","Profit","Positions","Invested",
"VolBuy","VolSell","ProfitBuy","ProfitSell","EffBuy","EffSell");
FileClose(dataoutput);
}
Metadata.Save(MyName);
}
//if (Assets.timer.UpdateTime(Forex1,9))
if (Assets.timer.UpdateTime(Forex1,THour,TMin))
{
Print("Ontick:",Assets.timer.LastUpdate," ",TimeLocal());
Assets.Rank(TableTimeframe,TablePeriod,TableAtrTimeframe,TableAtrPeriod,TablePeriodicity);
Assets.Select(RSTFixedAssets,Money.Balance()/*,liqfrac,liqper,liqtime,liqrefsymb*/,premin);
if(UseRenorm) Assets.Renorm(Alavancagem*Money.Balance());
Assets.timer.SetLastUpdate(9);
for (int i=0;i<ArraySize(Assets.data);i++)
{
Assets.data[i].mydata.StrategyB1.myvol=Assets.data[i].vol;
Assets.data[i].mydata.StrategyB2.myvol=Assets.data[i].vol;
Assets.data[i].mydata.StrategyS1.myvol=Assets.data[i].vol;
Assets.data[i].mydata.StrategyS2.myvol=Assets.data[i].vol;
}
Assets.PrintTable();
if((!MQLInfoInteger(MQL_OPTIMIZATION))&&(!MQLInfoInteger(MQL_TESTER)))
{
Assets.SaveConfig(MyName+".bin");
}
if (SaveTable) Assets.SaveTable(MyName+"-carteira.csv");
}
if (UseTimer&&(ThisTimer.UpdateTime(Forex1,OHour,OMin)))
{
for (int i=0;i<ArraySize(Assets.data);i++)
if (Assets.data[i].selected||PositionSelect(Assets.data[i].ticker))//só chama se for selecionado ou se tiver posição
ontick(Assets.data[i],Money.MarginFree(Assets.data));//para permitir o fechamento de posições fora da tabela
ThisTimer.SetLastUpdate();
}
else if (!UseTimer)
{
for (int i=0;i<ArraySize(Assets.data);i++)
if (Assets.data[i].selected||PositionSelect(Assets.data[i].ticker))
ontick(Assets.data[i],Money.MarginFree(Assets.data));//chama para todos, para permitir o fechamento de posições fora da tabela
}
return;
}
void NONE(void){return;}
void ontick(AssetData &data,double FreeMargin)
{
string psymbol=data.ticker;
CLock* lock=data.mydata.Lock;
PLock* poslock=data.mydata.PosLock;
ALock* assetlock=data.mydata.AssetLock;
Signal* StrategyB1=data.mydata.StrategyB1;
Signal* StrategyB2=data.mydata.StrategyB2;
Signal* StrategyS1=data.mydata.StrategyS1;
Signal* StrategyS2=data.mydata.StrategyS2;
Filters* Liquidity=data.mydata.Liquidity;
Filters* PriceMin=data.mydata.PriceMin;
OrderData* PosData=data.mydata.PosData;
double VolLimitFrac=VolLimit*TimerPeriod*4/Dia;//O 4 é por causa da duração do pregão
if (!UseVolLimit) VolLimitFrac=1;
if (Bars(psymbol,PERIOD_D1)<10) return;
MqlDateTime today,stime,ltime;
TimeCurrent(today);
TimeLocal(ltime);
MqlRates rttemp[];
ArraySetAsSeries(rttemp,true);
CopyRates(psymbol,PERIOD_D1,0,1,rttemp);
TimeToStruct(rttemp[0].time,stime);
if (!Forex1&&((today.day!=ltime.day)||(today.day!=stime.day))) return;
bool not_locked=lock.CheckLock(psymbol,LockExp);//essa trava destrava se tem pendente
bool isonline=(!MQLInfoInteger(MQL_TESTER))&&(!MQLInfoInteger(MQL_OPTIMIZATION));
bool auction=(SymbolInfoDouble(psymbol,SYMBOL_ASK)<=SymbolInfoDouble(psymbol,SYMBOL_BID));
bool possel=PositionSelect(psymbol);
//int MyMagic=-100;
bool pending=CheckOrders(psymbol,ALL_LOCKS);
bool assetnotlocked=false;
if (isonline&&UseAssetLock&&(!pending))//reseta a trava de ativos. Só reseta se não tem posição. Mas e se tiver pendente?
{
if (!possel) assetlock.ResetLock();
assetnotlocked=assetlock.CheckLock(EAMAGIC);
}
else assetnotlocked=true;//testing e optimization
if (possel&&data.selected&&isonline&&PosTake&&UseAssetLock&&(!pending))//tomada de posição //Só se tiver posição. Mas e se tiver pendente?
if (assetlock.CheckPosTake(EAMAGIC))
assetlock.SetPosTake(EAMAGIC);
//Reseta position data se não tem ordem, nem posição, nem trava e o ativo é meu e usamos ordens pendentes para alguma coisa
if ((!possel)&&(!pending)&&(not_locked)
&&((UseAssetLock&&isonline)?assetlock.CheckOwner(EAMAGIC):true)&&
(UsePendingClose||UsePendingOpen||UsePendingSl||UsePendingTp))
{
double sl,tp,priceref,atr,target;
datetime lasttime;
OrderTypes ot;
PosData.GetPositionData(sl,tp,ot,priceref,atr,target,lasttime);
if (ot!=OTNone) PosData.Reset();
}
//if (possel&&assetnotlocked)
if (possel&&(!pending)&&((UseAssetLock&&isonline)?assetlock.CheckOwner(EAMAGIC):true)
&&(Forex1?true:(((today.hour>=OHour)&&(today.min>=OMin))||(today.hour>=(OHour+1))))//horário de abertura
&&(!auction)
&&TerminalInfoInteger(TERMINAL_CONNECTED)//conectado
&&TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)//negociação habilitada
)//só mexa na posição se ela for minha e não tiver pendentes
{
poslock.SetLock();
if ((not_locked)&&(!data.selected))//ativo não selecionado
{
if (UsePendingClose)
{
double sl,tp,priceref,atr,target;
datetime lasttime;
OrderTypes ot;
PosData.GetPositionData(sl,tp,ot,priceref,atr,target,lasttime);
double bid=SymbolInfoDouble(psymbol,SYMBOL_BID),ask=SymbolInfoDouble(psymbol,SYMBOL_ASK);
if (PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY) priceref=ask;//atr=Atr(psymbol,StrategyB1.patr,StrategyB1.timeframe);}
else if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL) priceref=bid;//atr=Atr(psymbol,StrategyS1.patr,StrategyS1.timeframe);}
//TODO: set the target
if (PosData.SetPositionData(sl,tp,OTClose,priceref,atr,target,TimeLocal()))
{
MyPrint("Fechando "+psymbol);
PositionClose(true,psymbol,lock,UseVolLimit,VolLimitFrac,data.mvol);
MyPrint("Posição fora do ranking ");
}
else MyPrint("Erro fechando "+psymbol);
return;
}
else
{
MyPrint("Fechando "+psymbol);
PositionClose(false,psymbol,lock,UseVolLimit,VolLimitFrac,data.mvol);
MyPrint("Posição fora do ranking ");
}
}
if (not_locked)//verifica se atingiu (pulou) sl/tp - neste caso, como o sl e o tp estão na posição, o protocolo é fechar imediatamente
//é possível pensar em uma rotina para o caso em que usamos ordens pendentes, nesse caso a informação sobre o sl tp teria que vir de algum
//lugar como o comentário da ordem ou consulta à estratégia. Pode ser aqui o lugar ideal para implementar isso
{
double sl=PositionGetDouble(POSITION_SL);
double tp=PositionGetDouble(POSITION_TP);
double priceref=0,atr=0,target=0;
datetime lasttime=0;
OrderTypes ot=OTNone;
if (UsePendingSl||UsePendingTp) PosData.GetPositionData(sl,tp,ot,priceref,atr,target,lasttime);
double last=rttemp[0].close;
double bid=SymbolInfoDouble(psymbol,SYMBOL_BID),ask=SymbolInfoDouble(psymbol,SYMBOL_ASK);
if (PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY) priceref=ask;
else if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL) priceref=bid;
//TODO: set the target
if (PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
{
if ((UsePendingSl)&&(last<=sl)&&(sl!=0))//stop loss
{
if (PosData.SetPositionData(sl,tp,OTSL,priceref,atr,target,TimeLocal()))
{
PositionClose(true,psymbol,lock,UseVolLimit,VolLimitFrac,data.mvol);
MyPrint("Fechando posição Buy, condição de sl atingida ",DoubleToString(last,2)," ",DoubleToString(sl,2)," ",DoubleToString(tp,2));
}
}
else if ((UsePendingTp)&&(last>=tp)&&(tp!=0))//take profit
{
if (PosData.SetPositionData(sl,tp,OTTP,priceref,atr,target,TimeLocal()))
{
PositionClose(true,psymbol,lock,UseVolLimit,VolLimitFrac,data.mvol);
MyPrint("Fechando posição Buy, condição de tp atingida ",DoubleToString(last,2)," ",DoubleToString(sl,2)," ",DoubleToString(tp,2));
}
}
else if ( ((last>tp)&&(tp!=0)) || ((last<sl)&&(sl!=0)) )//vefirica se o sl/tp foi pulado
{
PositionClose(false,psymbol,lock,UseVolLimit,VolLimitFrac,data.mvol);
MyPrint("Fechando posição Buy, condição de sl/tp pulada ",DoubleToString(last,2)," ",DoubleToString(sl,2)," ",DoubleToString(tp,2));
}
return;
}
if (PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL)
{
if ((UsePendingSl)&&(last>=sl)&&(sl!=0))//stop loss
{
if (PosData.SetPositionData(sl,tp,OTSL,priceref,atr,target,TimeLocal()))
{
PositionClose(true,psymbol,lock,UseVolLimit,VolLimitFrac,data.mvol);
MyPrint("Fechando posição Sell, condição de sl atingida ",DoubleToString(last,2)," ",DoubleToString(sl,2)," ",DoubleToString(tp,2));
}
}
else if ((UsePendingTp)&&(last<=tp)&&(tp!=0))//take profit
{
if (PosData.SetPositionData(sl,tp,OTTP,priceref,atr,target,TimeLocal()))
{
PositionClose(true,psymbol,lock,UseVolLimit,VolLimitFrac,data.mvol);
MyPrint("Fechando posição Sell, condição de tp atingida ",DoubleToString(last,2)," ",DoubleToString(sl,2)," ",DoubleToString(tp,2));
}
}
else if ( ((last<tp)&&(tp!=0)) || ((last>sl)&&(sl!=0)) )//vefirica se o sl/tp foi pulado
{
PositionClose(false,psymbol,lock,UseVolLimit,VolLimitFrac,data.mvol);
MyPrint("Fechando posição Sell, condição de sl/tp atingida ",DoubleToString(last,2)," ",DoubleToString(sl,2)," ",DoubleToString(tp,2));
}
return;
}
}
//MyMagic=(int)PositionGetInteger(POSITION_MAGIC);
//if (MyMagic==StrategyB1.BuyMagic)//modifica sl/tp, checa day trade
if (PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
{
if (PosExp) if (ExpiraPos(UsePendingClose,PosData,psymbol,PosExpB,not_locked,lock,UseVolLimit,VolLimitFrac,data.mvol)) return;
ModifySlTp(psymbol,Atr(psymbol,StrategyB1.patr,StrategyB1.timeframe),PosExp,PosExpB,Buy,UseTrailingSL,UseTrailingTP,PosExpTP,PosExpSL,
Sl_Type,SLLevel,SlTimeframe,SlBars,
Tp_Type,TPLevel,TpTimeframe,TpBars,
lock,not_locked,PositionGetDouble(POSITION_SL),PositionGetDouble(POSITION_TP),UsePendingSl,UsePendingTp);//só chama se não for usependingsltp
if (UseDTB) CheckDT(possel,psymbol,not_locked,lock,UseVolLimit,VolLimitFrac,data.mvol);//não fechar usando pendentes
}
else if (PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL)
//else if (MyMagic==StrategyS1.SellMagic)//modifica sl/tp, checa day trade
{
if (PosExp) if (ExpiraPos(UsePendingClose,PosData,psymbol,PosExpS,not_locked,lock,UseVolLimit,VolLimitFrac,data.mvol)) return;
ModifySlTp(psymbol,Atr(psymbol,StrategyS1.patr,StrategyS1.timeframe),PosExp,PosExpS,Sell,UseTrailingSL,UseTrailingTP,PosExpTP,PosExpSL,
Sl_Type,SLLevel,SlTimeframe,SlBars,
Tp_Type,TPLevel,TpTimeframe,TpBars,
lock,not_locked,PositionGetDouble(POSITION_SL),PositionGetDouble(POSITION_TP),UsePendingSl,UsePendingTp);//,(UsePendingClose||UsePendingOpen||UsePendingSLTP),PosData);
if (UseDTS) CheckDT(possel,psymbol,not_locked,lock,UseVolLimit,VolLimitFrac,data.mvol);//não fechar usando pendentes
}
/*else//Há uma posição sem o magic correto. Feche-a imediatamente
{
if ((not_locked)&&(MyMagic!=CLOSE_LOCK))
{
PositionClose(psymbol,lock,UseVolLimit,VolLimitFrac,data.mvol);
Print("Erro! Posição sem o magic correto "+IntegerToString(MyMagic));
}
return;
}*/
}
if ( ((today.hour>=OCHour)&&(today.min>=OCMin))||(today.hour>(OCHour)) )
{
StrategyB1.Reset();
StrategyS1.Reset();
StrategyB2.Reset();
StrategyS2.Reset();
}
if (possel&&pending)/*&&(!PersistSignal)*///se tem posição ou tem pendente, reseta o sinal
{
if (PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY) {StrategyB1.Reset();StrategyB2.Reset();}
if (PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL) {StrategyS1.Reset();StrategyS2.Reset();}
}
bool position_not_locked=poslock.CheckLock(psymbol,LockExp);//trava de posição retorna false se travado.
//Print(psymbol," ",count_stops(psymbol,DEAL_TYPE_SELL,StrategyB1.BuyMagic)," ",count_stops(psymbol,DEAL_TYPE_BUY,StrategyS1.SellMagic));
if ((not_locked)&&(!pending)//só abre nova se não tiver pendente
&&assetnotlocked
&&data.selected
&&(Forex1?true:(((today.hour>=OHour)&&(today.min>=OMin))||(today.hour>=(OHour+1))))//horário de abertura
&&(!auction)//evita leilão
&&TerminalInfoInteger(TERMINAL_CONNECTED)//conectado
&&TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)//negociação habilitada
)
{
if (EnableB&&(possel?
((UseCloseBy&&(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL))||
((PositionGetDouble(POSITION_VOLUME)!=data.vol)&&(UseRebal)))
:position_not_locked)//se não tem posição, só abre nova se não tiver trava de posição
&&StrategyB1.SignalCheck(Buy)
&&(possel?true:StrategyB2.SignalCheck(Buy))//só checa o sinal da segunda estratégia se não tiver posição
&&(!(UseDTB?CheckDT(false,psymbol,not_locked,lock,UseVolLimit,VolLimitFrac,data.mvol):false))
&&(count_stops(psymbol,DEAL_TYPE_SELL,StrategyB1.BuyMagic)<1)
&&(possel?true:(UseFilter1?(!Liquidity.Filter(Buy)):true))//só checa os filtros se não tiver posição
&&(possel?true:(UseFilter2?(!PriceMin.Filter(Buy)):true))
&&(possel?true:(MGMTMargin?(FreeMargin>=(data.vol*rttemp[0].close)):true))//só checa margem se não tiver posição
)
{
if ((possel)&&(UseCloseBy)) Trade.PositionClose(psymbol);//não usar pendente
double myvol=TradeSizeOptimized(psymbol,StrategyB1.Vol(),true);
if (UseVolLimit&&(myvol>(VolLimitFrac*data.mvol))) myvol=TradeSizeOptimized(psymbol,VolLimitFrac*data.mvol,true);//limita o volume a x% da média
if ((UseAssetLock&&isonline)?assetlock.SetLock(EAMAGIC):true)
{
if (UsePendingOpen)
{
//TODO: set the target
if (PosData.SetPositionData(StrategyB1.Sl(),StrategyB1.Tp(),OTOpen,SymbolInfoDouble(psymbol,SYMBOL_BID),Atr(psymbol,StrategyB1.patr,StrategyB1.timeframe,0),0,TimeLocal()))
if (open_buy(psymbol,Atr(psymbol,StrategyB1.patr,StrategyB1.timeframe,0),myvol,
Sl_Type,SLLevel,SlTimeframe,SlBars,
Tp_Type,TPLevel,TpTimeframe,TpBars,
"Buy ",(possel?(int)PositionGetInteger(POSITION_MAGIC):StrategyB1.BuyMagic),
UsePendingOpen,OrderSlippage,
lock,
StrategyB1.Sl(),
StrategyB1.Tp()))
return;
}
else
{
if (open_buy(psymbol,Atr(psymbol,StrategyB1.patr,StrategyB1.timeframe,0),myvol,
Sl_Type,SLLevel,SlTimeframe,SlBars,
Tp_Type,TPLevel,TpTimeframe,TpBars,
"Buy ",(possel?(int)PositionGetInteger(POSITION_MAGIC):StrategyB1.BuyMagic),
UsePendingOpen,OrderSlippage,
lock,
StrategyB1.Sl(),
StrategyB1.Tp()))
return;
}
}
}
if (EnableS&&(possel?
((UseCloseBy&&(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY))||
((PositionGetDouble(POSITION_VOLUME)!=data.vol)&&(UseRebal)))
:position_not_locked)
&&StrategyS1.SignalCheck(Sell)
&&(possel?true:StrategyS2.SignalCheck(Sell))//só checa o sinal da segunda estratégia se não tiver posição
&&(!(UseDTS?CheckDT(false,psymbol,not_locked,lock,UseVolLimit,VolLimitFrac,data.mvol):false))
&&(count_stops(psymbol,DEAL_TYPE_BUY,StrategyS1.SellMagic)<1)
&&(possel?true:(UseFilter1?(!Liquidity.Filter(Sell)):true))//só checa os filtros se não tiver posição
&&(possel?true:(UseFilter2?(!PriceMin.Filter(Sell)):true))
&&(possel?true:(MGMTMargin?(FreeMargin>=(data.vol*rttemp[0].close)):true))//só checa margem se não tiver posição
)
{
if ((possel)&&(UseCloseBy)) Trade.PositionClose(psymbol);//não usar pendente
double myvol=TradeSizeOptimized(psymbol,StrategyS1.Vol(),true);
if (UseVolLimit&&(myvol>(VolLimitFrac*data.mvol))) myvol=TradeSizeOptimized(psymbol,VolLimitFrac*data.mvol,true);//limita o volume a x% da média
//myvol=TradeSizeOptimized(psymbol,StrategyS1.Vol()/2.0,false);//parcela a ordem
//Print(assetlock.SetLock(EAMAGIC)," ",psymbol);
if ((UseAssetLock&&isonline)?assetlock.SetLock(EAMAGIC):true)
{
if (UsePendingOpen)
{
//TODO: set the target
if(PosData.SetPositionData(StrategyS1.Sl(),StrategyS1.Tp(),OTOpen,SymbolInfoDouble(psymbol,SYMBOL_ASK),Atr(psymbol,StrategyS1.patr,StrategyS1.timeframe,0),0,TimeLocal()))
if (open_sell(psymbol,Atr(psymbol,StrategyS1.patr,StrategyS1.timeframe,0),myvol,
Sl_Type,SLLevel,SlTimeframe,SlBars,
Tp_Type,TPLevel,TpTimeframe,TpBars,
"Sell ",(possel?(int)PositionGetInteger(POSITION_MAGIC):StrategyS1.SellMagic),
UsePendingOpen,OrderSlippage,
lock,
StrategyS1.Sl(),
StrategyS1.Tp()))
return;
}
else
{
if (open_sell(psymbol,Atr(psymbol,StrategyS1.patr,StrategyS1.timeframe,0),myvol,
Sl_Type,SLLevel,SlTimeframe,SlBars,
Tp_Type,TPLevel,TpTimeframe,TpBars,
"Sell ",(possel?(int)PositionGetInteger(POSITION_MAGIC):StrategyS1.SellMagic),
UsePendingOpen,OrderSlippage,
lock,
StrategyS1.Sl(),
StrategyS1.Tp()))
return;
}
}
}
}
if (pending)
{
PosData.CheckPendingExpiration(OrdExp,auction);//verifica expiração da pendente e deleta
if ((UseTrailingOp)&&(PosData.order_type==OTOpen))
PosData.OrderTrailing(TrailingTopOp,TrailingMountainOp,TrailingSoma1Op,TrailingEscapeOp,TrailingTargetOp,TrailingTolOp,TrailingTolFracOp,TrailingAggressionOp);
else if ((UseTrailingCl)&&(PosData.order_type==OTClose))
PosData.OrderTrailing(TrailingTopCl,TrailingMountainCl,TrailingSoma1Cl,TrailingEscapeCl,TrailingTargetCl,TrailingTolCl,TrailingTolFracCl,TrailingAggressionCl);
else if ((UseTrailingSl)&&(PosData.order_type==OTSL))
PosData.OrderTrailing(TrailingTopSl,TrailingMountainSl,TrailingSoma1Sl,TrailingEscapeSl,TrailingTargetSl,TrailingTolSl,TrailingTolFracSl,TrailingAggressionSl);
else if ((UseTrailingTp)&&(PosData.order_type==OTTP))
PosData.OrderTrailing(TrailingTopTp,TrailingMountainTp,TrailingSoma1Tp,TrailingEscapeTp,TrailingTargetTp,TrailingTolTp,TrailingTolFracTp,TrailingAggressionTp);
}
return;
}
void InitStrategy(Signal* &strategy,MODEL_TYPES EModelType,string Asymbol,int EPAtrB,ENUM_TIMEFRAMES ETimeFrameB,
REF_TYPES EType,REF_PRICES_TYPES EPrice,int EPeriodo,ENUM_TIMEFRAMES ERefTimeFrame,double EAtrFrac,bool EConfCandle,double volume)
{
switch (EModelType)
{
case Buy_hold:
{
strategy=new BuyHold;
strategy.Init();
strategy.Initfixed(Asymbol,EPAtrB,ETimeFrameB,BUY_HOLD_MAGIC,BUY_HOLD_MAGIC+1,volume);
break;
}
case Buy_hold_sell_neutral:
{
strategy=new BuyHoldSellNeutral;
strategy.Init();
strategy.Initfixed(Asymbol,EPAtrB,ETimeFrameB,BUY_HOLD_MAGIC,BUY_HOLD_MAGIC+1,volume);
break;
}
case Sell_hold:
{
strategy=new SellHold;
strategy.Init();
strategy.Initfixed(Asymbol,EPAtrB,ETimeFrameB,SELL_HOLD_MAGIC,SELL_HOLD_MAGIC+1,volume);
break;
}
case Tendencia:
{
strategy=new Trend;
strategy.Init();
strategy.Initfixed(Asymbol,EPAtrB,ETimeFrameB,TREND_MAGIC,TREND_MAGIC+1,volume);
double params[6];
params[0]=(double)EType;
params[1]=(double)EPrice;
params[2]=(double)EPeriodo;
params[3]=(double)EAtrFrac;
params[4]=(double)EConfCandle;
params[5]=(double)ERefTimeFrame;
strategy.Initspecific(params);
break;
}
case Retorno:
{
strategy=new Return;
strategy.Init();
strategy.Initfixed(Asymbol,EPAtrB,ETimeFrameB,RETURN_MAGIC,RETURN_MAGIC+1,volume);
double params[6];
params[0]=(double)EType;
params[1]=(double)EPrice;
params[2]=(double)EPeriodo;
params[3]=(double)EAtrFrac;
params[4]=(double)EConfCandle;
params[5]=(double)ERefTimeFrame;
strategy.Initspecific(params);
break;
}
case Gap_alta_baixa:
{
strategy=new Gap;
strategy.Init();
strategy.Initfixed(Asymbol,EPAtrB,ETimeFrameB,GAP_MAGIC,GAP_MAGIC+1,volume);
break;
}
case Python_scripts:
{
strategy=new PythonScripts;
strategy.Init();
strategy.Initfixed(Asymbol,EPAtrB,ETimeFrameB,PYTHON_MAGIC,PYTHON_MAGIC+1,volume);
strategy.InitFname(python_fname);
double params[2];
params[0]=(double)UsePythonTicker;//useticker
params[1]=(double)UsePythonVolume;//usevolume
break;
}
}
}
int OnInit()
{
if (UseNeutralization)
{
MyTickers[ArraySize(MyTickers)-1]=NeutralAsset2;
MyTickers[ArraySize(MyTickers)-2]=NeutralAsset1;
}
//Sleep(60*1000);//bug no reinício do metatrader
srand(SeedMonteCarlo);
Trade.SetAsyncMode(false);
MyName=EAName+"-Avalon";//+StringSubstr(TableFile,0,4);
Money.mgmt=MGMTType;
Money.MyCapital=mycapital;
Money.MyMargin=mymargin;
Money.MyMarginFrac=mymarginfrac;
if ((FileIsExist(MyName+".bin"))&&(!MQLInfoInteger(MQL_OPTIMIZATION))&&(!MQLInfoInteger(MQL_TESTER)))
{
Assets.LoadConfig(MyName+".bin");
if (ChangeCapital)
{
Assets.Redim(Alavancagem*Money.Balance());
Assets.timer.SetLastUpdate(9);
Assets.PrintTable();
if((!MQLInfoInteger(MQL_OPTIMIZATION))&&(!MQLInfoInteger(MQL_TESTER))) Assets.SaveConfig(MyName+".bin");
if (SaveTable) Assets.SaveTable(MyName+"-carteira.csv");
}
Print(Assets.timer.LastUpdate," ",TimeLocal());
}
else
{
Assets.timer.Periodicidade=TablePeriodicity;
Assets.MyRankSelection=MySelectionType;//RSTFixed;//RSTCharge;//RSTPositive;
Assets.MyRank=MyRank;
Assets.UseLiqFilter=UseTableLiqFilter;
Assets.UsePreFilter=UseTablePreFilter;
Assets.UseLowVolFilter=UseTableLowVolFilter;
//Assets.Read(TableFile,EnableMonteCarlo,NativosMonteCarlo);//ativos[0]=Symbol();
Assets.Read(EnableMonteCarlo,NativosMonteCarlo);//ativos[0]=Symbol();
Assets.Rank(TableTimeframe,TablePeriod,TableAtrTimeframe,TableAtrPeriod,TablePeriodicity);
Assets.Select(RSTFixedAssets,Money.Balance()/*,liqfrac,liqper,liqtime,liqrefsymb*/,premin);
if(UseRenorm) Assets.Renorm(Alavancagem*Money.Balance());
Assets.timer.SetLastUpdate(9);
//Assets.timer.LastUpdate=Assets.timer.Periodicidade*(datetime)floor(TimeLocal()/Assets.timer.Periodicidade);
Assets.PrintTable();
if((!MQLInfoInteger(MQL_OPTIMIZATION))&&(!MQLInfoInteger(MQL_TESTER)))
{
Assets.SaveConfig(MyName+".bin");//deve ter uma opção para salvar a configuração
}
//if (SaveTable) Assets.SaveTable(MyName+"-"+TimeToString(TimeCurrent(),TIME_DATE)+"-carteira.csv");
if (SaveTable) Assets.SaveTable(MyName+"-carteira.csv");
}
for(int i=0;i<ArraySize(Assets.data);i++)
{
string Asymbol=Assets.data[i].ticker;
Assets.data[i].mydata.Lock=new CLock;
Assets.data[i].mydata.Lock.ResetLock();
Assets.data[i].mydata.PosLock=new PLock;
Assets.data[i].mydata.PosLock.ResetLock();
Assets.data[i].mydata.AssetLock=new ALock;
if ((!MQLInfoInteger(MQL_TESTER))&&(!MQLInfoInteger(MQL_OPTIMIZATION))&&UseAssetLock)
Assets.data[i].mydata.AssetLock.InitLock(Asymbol);
if (UseBook) MarketBookAdd(Asymbol);
InitStrategy(Assets.data[i].mydata.StrategyB1,E1ModelType,Asymbol,E1PAtrB,E1TimeFrameB,E1Type,E1Price,E1Periodo,E1RefTimeFrame,E1AtrFrac,E1ConfCandle,Assets.data[i].vol);
InitStrategy(Assets.data[i].mydata.StrategyS1,E1ModelType,Asymbol,E1PAtrS,E1TimeFrameS,E1Type,E1Price,E1Periodo,E1RefTimeFrame,E1AtrFrac,E1ConfCandle,Assets.data[i].vol);
InitStrategy(Assets.data[i].mydata.StrategyB2,E2ModelType,Asymbol,E2PAtrB,E2TimeFrameB,E2Type,E2Price,E2Periodo,E2RefTimeFrame,E2AtrFrac,E2ConfCandle,Assets.data[i].vol);
InitStrategy(Assets.data[i].mydata.StrategyS2,E2ModelType,Asymbol,E2PAtrS,E2TimeFrameS,E2Type,E2Price,E2Periodo,E2RefTimeFrame,E2AtrFrac,E2ConfCandle,Assets.data[i].vol);
Assets.data[i].mydata.Liquidity=new Filters;
Assets.data[i].mydata.Liquidity.symbol=Asymbol;
Assets.data[i].mydata.Liquidity.myfilter=MyFilter1;
Assets.data[i].mydata.Liquidity.FTLiqFrac=LiqFrac1;
Assets.data[i].mydata.Liquidity.FTPeriod=FPeriod1;
Assets.data[i].mydata.Liquidity.FTTimeframe=FTimeFrame1;
Assets.data[i].mydata.Liquidity.FTLiqSymbolref=FSymbol1;
Assets.data[i].mydata.PriceMin=new Filters;
Assets.data[i].mydata.PriceMin.symbol=Asymbol;
Assets.data[i].mydata.PriceMin.myfilter=MyFilter2;
Assets.data[i].mydata.PriceMin.FTPreMin=PreMin2;
Assets.data[i].mydata.PosData=new OrderData;
if (UsePendingClose||UsePendingOpen||UsePendingSl||UsePendingTp) Assets.data[i].mydata.PosData.InitPositionData(Asymbol);
}
ThisTimer.Periodicidade=TimerPeriod;
Metadata.timer.Periodicidade=SaveDataPeriod;
Metadata.SymbolRef=SaveSymbolRef;//Symbol();
Metadata.DataFname=TimeToString(TimeLocal(),TIME_DATE)+"-data.csv";
if (!FileIsExist(MyName+Metadata.DataFname))
{
int dataoutput=FileOpen(MyName+Metadata.DataFname,FILE_READ|FILE_WRITE|FILE_CSV|FILE_ANSI,';',CP_UTF8);
FileWrite(dataoutput,"Date",Metadata.SymbolRef,"Equity","Balance","Profit","Positions","Invested",
"VolBuy","VolSell","ProfitBuy","ProfitSell","EffBuy","EffSell");
FileClose(dataoutput);
}
if ((!MQLInfoInteger(MQL_TESTER))&&(!MQLInfoInteger(MQL_OPTIMIZATION))) EventSetTimer(1);//online
else if (MakePdf&&(MQLInfoInteger(MQL_TESTER))&&(!MQLInfoInteger(MQL_OPTIMIZATION))) //grava report
{
EventSetTimer(4*3600);
Reportdata.timer.Periodicidade=Dia;
Reportdata.SymbolRef=SaveSymbolRef;
Reportdata.DataFname="report.csv";
}
if (UseTelegram)
{
int datatoken=FileOpen(EAName+"Token.txt",FILE_READ|FILE_TXT);
ThisBot.Init(FileReadString(datatoken));
FileClose(datatoken);
}
Print("Init finished");
return(INIT_SUCCEEDED);
}