Transmitir parâmetros de entrada diferentes. Símbolo, período, parâmetros de entrada são os mesmos, indicador é o mesmo. O terminal tenta minimizar o consumo de recursos e, neste caso, não é criada uma nova cópia do indicador, ou seja, funciona efectivamente um programa mql5.
Por favor, ajude-me a corrigi-lo. No Testador de Estratégia tudo funciona perfeitamente, mas na demonstração RTS em m1 por vezes em vez de uma posição de 3 lotes envia 2 encomendas de 3 lotes cada, e a posição total de 6 lotes.
#property copyright "Copyright 2013, DKeN"#property link ""#property version "1.00"/*
1 Название: Параболик
2 Терминал: МТ5
3 Рабочий инструмент: любой инструмент и период
4 Индикатор: параболик
5 Правила:
при пересечение входим в направлении пересечения по рынку ,
профит делим на 3 части , при закрытие первого выставляем стоп в ноль или чуть в плюс,
если профит не достигнут, а цена ушла в минус переворачиваем позицию при пересечении параболика…
6 второй вариант: при пересечение входим в направлении пересечения по рынку , профит делим на 2 части , при закрытие первой части вторую оставляем до пересечения параболика
7 настройки: а) к-во лотов
б) индикатор
в) время работы
8. возможность работы по нескольким инструментам на одном счете
если торгуем на РТС необходимо строго со спецификацией инструмента данные задавать!
*/inputstring comment="";
//комментарий к ордеруinputint slippage=10;
//проскальзываниеinputdouble lot=3;
//рабочий лот позицииinputint takeprofit=200;
//тейк профит основной позицииinputint stoploss=1000;
//стоп лосс основной позицииinputint mode=1;
/*режим выхода 1 или 2*/inputint takeprofit1=100;
//точка закрытия первой части профита в пунктахinputdouble lot1=1;
//объем закрываемой части ордераinputdouble bu1=10;
//для режима 1, пренос в безубыток +1inputint takeprofit2=150;
//точка закрытия второй части профита в пунктахinputdouble lot2=1;
//объем закрываемой позицииinputENUM_TIMEFRAMES tf=0;
//период, 0 - по умолчанию с графика текущийinputdouble step=0.02;
inputdouble maximum=0.2;
//настрйоки для сар step,maximuminputstring times="00:00-24:00";
//поддерживаются интервалы через , например 00:00-12:00, 16:00-20:00 и т.д. поддержка ночного перехода например 22:00-05:00//+------------------------------------------------------------------+//| Expert initialization function |//+------------------------------------------------------------------+int psar=-1;
ulong semafor=0;
intOnInit()
{
//---
psar=iSAR(NULL,tf,step,maximum);
if(psar==INVALID_HANDLE){
PrintFormat("Не удалось создать хэндл индикатора iSAR для пары %s/%s, код ошибки %d", _Symbol, EnumToString(_Period),GetLastError());
return (-1);
}
semafor=0;
//---return(0);
}
//+------------------------------------------------------------------+//| Expert deinitialization function |//+------------------------------------------------------------------+voidOnDeinit(constint reason)
{
//---if(psar!=INVALID_HANDLE) IndicatorRelease(psar);
Comment("");
}
//+------------------------------------------------------------------+//| Expert tick function |//+------------------------------------------------------------------+voidOnTick()
{
//---bool bWork=time_check(times);
Comment("Торговый интервал времени");
if(!bWork)Comment("Неторговый интервал времени. Разрешено закрытие по обратному сигналу и частичное закрытие. Открытие новых сделок запрещено.");
double sar[],dLot,open,stop,take;
ENUM_POSITION_TYPE type;
ArraySetAsSeries(sar,true);
string n=_Symbol;
if(CopyBuffer(psar,0,0,2,sar)>=0){
//1 - предыдущее значение//0 - текущий барMqlRates rates[];
MqlTick tick;
ArraySetAsSeries(rates,true);
int op=0;
if(CopyRates(NULL,tf,0,2,rates)>0){
if(SymbolInfoTick(n,tick)){
if(tick.bid<sar[1] && sar[1]<rates[0].open) op=-1;
elseif(tick.ask>sar[1] && sar[1]>rates[0].open) op=1;
}
//првоерим если позиции в рынке нет, попробуем открыть по сигналуif(!PositionSelect(n)) {
order_OrderDeleteAll(n); //удалим отложкиif(op==0) return; //сигнала нет! if(bWork){
if(op==1) order_OrderSend(n,ORDER_TYPE_BUY,lot,0,stoploss,takeprofit,comment);
if(op==-1) order_OrderSend(n,ORDER_TYPE_SELL,lot,0,stoploss,takeprofit,comment);
}
}else{
type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
dLot=PositionGetDouble(POSITION_VOLUME);
if(dLot==lot){
int orders[];
int all=order_OrdersTotal(n,orders);
open=PositionGetDouble(POSITION_PRICE_OPEN);
if(type==POSITION_TYPE_BUY && orders[ORDER_TYPE_SELL_LIMIT]==0){
if(mode==2 || mode==1)order_OrderSend(n,ORDER_TYPE_SELL_LIMIT,lot1,open+takeprofit1*_Point,0,0,"");
if(mode==1)order_OrderSend(n,ORDER_TYPE_SELL_LIMIT,lot2,open+takeprofit2*_Point,0,0,"");
}
if(type==POSITION_TYPE_SELL && orders[ORDER_TYPE_BUY_LIMIT]==0){
if(mode==2 || mode==1)order_OrderSend(n,ORDER_TYPE_BUY_LIMIT,lot1,open-takeprofit1*_Point,0,0,"");
if(mode==1)order_OrderSend(n,ORDER_TYPE_BUY_LIMIT,lot2,open-takeprofit2*_Point,0,0,"");
}
}elseif(dLot<lot && mode==1){
open=PositionGetDouble(POSITION_PRICE_OPEN);
stop=PositionGetDouble(POSITION_SL);
take=PositionGetDouble(POSITION_TP);
if(type==POSITION_TYPE_BUY && (stop<open || stop==0.0)) order_OrderModify(n,open+bu1*_Point,take);
if(type==POSITION_TYPE_SELL && (stop>open || stop==0.0)) order_OrderModify(n,open-bu1*_Point,take);
}
//Print(GetLastError()," op=",op," type=",type); if(op==0) return;
//позиция к этому моменту могла быть уже закрыта, перепроверим и проверим ее лот и типif(PositionSelect(n)){
type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
dLot=PositionGetDouble(POSITION_VOLUME);
//осуществим переворот, да так чтобы закрыть остаток и открыть начальным лотомif(type==POSITION_TYPE_BUY && op==-1) {
order_OrderDeleteAll(n); //удалим отложки
order_OrderSend(n,ORDER_TYPE_SELL,dLot,0,0,0,comment);
}elseif(type==POSITION_TYPE_SELL && op==1) {
order_OrderDeleteAll(n); //удалим отложки
order_OrderSend(n,ORDER_TYPE_BUY,dLot,0,0,0,comment);
}
}
}
}
}
}
//+------------------------------------------------------------------+bool order_OrderModify(string name,double sl,double tp){
/*
SL & TP Modification
Торговый приказ на модификацию уровней StopLoss и/или TakeProfit. Требуется указание 4 полей:
action
symbol
sl
tp
*/MqlTradeRequest rq={0}; // структура запросаMqlTradeResult rs={0};
rq.action=TRADE_ACTION_SLTP;
rq.symbol=name;
rq.sl=sl;
rq.tp=tp;
return (OrderSend(rq,rs));
}
bool order_OrderSend(string name,ENUM_ORDER_TYPE type,double dlot,double open,double sl,double tp,string cmt){
MqlTradeRequest rq={0}; // структура запросаMqlTradeResult rs={0};
MqlTick tick={0};
MqlTradeCheckResult cr={0};
if(PositionSelect(name)) semafor=0;
if(semafor>0) return (false);
if(type==ORDER_TYPE_BUY || type==ORDER_TYPE_SELL){
rq.action=TRADE_ACTION_DEAL;
rq.symbol=name;
rq.volume=NLot(name,dlot);
rq.type=type;
bool ntick=SymbolInfoTick(name,tick);
if(open<=0){
if(type==ORDER_TYPE_BUY) rq.price=tick.ask;
elseif(type==ORDER_TYPE_SELL) rq.price=tick.bid;
}else{
rq.price=open; //если цена указана явно, то откроем по цене+проскальзывание
}
rq.sl=0;
rq.tp=0;
//выставим стопif(sl>0 && type==ORDER_TYPE_BUY) rq.sl=NormalizeDouble(rq.price-sl*_Point,_Digits);
elseif(sl>0 && type==ORDER_TYPE_SELL) rq.sl=NormalizeDouble(rq.price+sl*_Point,_Digits);
//выставим тейкif(tp>0 && type==ORDER_TYPE_BUY) rq.tp=NormalizeDouble(rq.price+tp*_Point,_Digits);
elseif(tp>0 && type==ORDER_TYPE_SELL) rq.tp=NormalizeDouble(rq.price-tp*_Point,_Digits);
rq.deviation=slippage;//допустимое проскальзывание
rq.type_filling=ORDER_FILLING_FOK;
rq.comment=cmt;
}else{
rq.action=TRADE_ACTION_PENDING;
rq.symbol=name;
rq.volume=NLot(name,dlot);
rq.type=type;
rq.deviation=slippage;//допустимое проскальзывание
rq.type_time=ORDER_TIME_DAY;
//ORDER_TIME_GTC; //ордер будет до снятия его программно или вручную//bool ntick=SymbolInfoTick(name,tick);
rq.price=open;
rq.sl=sl; //должна быть ценой!
rq.tp=tp;
rq.type_filling=ORDER_FILLING_RETURN;
rq.comment=cmt;
}
if(OrderCheck(rq,cr)){
if(OrderSend(rq,rs)){
if(rs.retcode!=TRADE_RETCODE_DONE && rs.retcode!=TRADE_RETCODE_PLACED){
Comment("Debug: order_OrderSend(retcode=",ResultRetcodeDescription(cr.retcode),")");
}
semafor=rs.deal;
if(rs.retcode==TRADE_RETCODE_DONE || rs.retcode==TRADE_RETCODE_PLACED){
if(type==ORDER_TYPE_BUY || type==ORDER_TYPE_SELL){
rq.action= TRADE_ACTION_SLTP;
rq.order= rs.order;
return (OrderSend(rq,rs));
}
}
return (true);
}
}else{
semafor=0;
Comment("Debug: order_OrderSend(retcode=",ResultRetcodeDescription(cr.retcode),")");
}
return (false);
}
/*удаляет отложки*/bool order_OrderDeleteAll(string name){
ulong ticket;
MqlTradeRequest rq={0};
MqlTradeResult rs={0};
for(int i=OrdersTotal()-1;i>=0;i--){
if((ticket=OrderGetTicket(i))>0){
ZeroMemory(rq);
ZeroMemory(rs);
rq.action=TRADE_ACTION_REMOVE;
rq.order=ticket;
OrderSend(rq,rs);
}
}
return (false);
}
int order_OrdersTotal(string name,int &orders[]){
ulong ticket;
int total=0;
ArrayResize(orders,10,0);
ArrayInitialize(orders,0);
//--- пройдем по всем отложенным ордерамfor(int i=OrdersTotal()-1;i>=0;i--)
if((ticket=OrderGetTicket(i))>0)
if(OrderGetString(ORDER_SYMBOL)==name){
orders[(int)OrderGetInteger(ORDER_TYPE)]++;
total++;
}
//---return(total);
}
//+------------------------------------------------------------------+ //| возврат стрингового результата торговой операции по его коду | //+------------------------------------------------------------------+ string ResultRetcodeDescription(int retcode)
{
string str;
//---- switch(retcode)
{
caseTRADE_RETCODE_REQUOTE: str="Реквота"; break;
caseTRADE_RETCODE_REJECT: str="Запрос отвергнут"; break;
caseTRADE_RETCODE_CANCEL: str="Запрос отменен трейдером"; break;
caseTRADE_RETCODE_PLACED: str="Ордер размещен"; break;
caseTRADE_RETCODE_DONE: str="Заявка выполнена"; break;
caseTRADE_RETCODE_DONE_PARTIAL: str="Заявка выполнена частично"; break;
caseTRADE_RETCODE_ERROR: str="Ошибка обработки запроса"; break;
caseTRADE_RETCODE_TIMEOUT: str="Запрос отменен по истечению времени";break;
caseTRADE_RETCODE_INVALID: str="Неправильный запрос"; break;
caseTRADE_RETCODE_INVALID_VOLUME: str="Неправильный объем в запросе"; break;
caseTRADE_RETCODE_INVALID_PRICE: str="Неправильная цена в запросе"; break;
caseTRADE_RETCODE_INVALID_STOPS: str="Неправильные стопы в запросе"; break;
caseTRADE_RETCODE_TRADE_DISABLED: str="Торговля запрещена"; break;
caseTRADE_RETCODE_MARKET_CLOSED: str="Рынок закрыт"; break;
caseTRADE_RETCODE_NO_MONEY: str="Нет достаточных денежных средств для выполнения запроса"; break;
caseTRADE_RETCODE_PRICE_CHANGED: str="Цены изменились"; break;
caseTRADE_RETCODE_PRICE_OFF: str="Отсутствуют котировки для обработки запроса"; break;
caseTRADE_RETCODE_INVALID_EXPIRATION: str="Неверная дата истечения ордера в запросе"; break;
caseTRADE_RETCODE_ORDER_CHANGED: str="Состояние ордера изменилось"; break;
caseTRADE_RETCODE_TOO_MANY_REQUESTS: str="Слишком частые запросы"; break;
caseTRADE_RETCODE_NO_CHANGES: str="В запросе нет изменений"; break;
caseTRADE_RETCODE_SERVER_DISABLES_AT: str="Автотрейдинг запрещен сервером"; break;
caseTRADE_RETCODE_CLIENT_DISABLES_AT: str="Автотрейдинг запрещен клиентским терминалом"; break;
caseTRADE_RETCODE_LOCKED: str="Запрос заблокирован для обработки"; break;
caseTRADE_RETCODE_FROZEN: str="Ордер или позиция заморожены"; break;
caseTRADE_RETCODE_INVALID_FILL: str="Указан неподдерживаемый тип исполнения ордера по остатку "; break;
caseTRADE_RETCODE_CONNECTION: str="Нет соединения с торговым сервером"; break;
caseTRADE_RETCODE_ONLY_REAL: str="Операция разрешена только для реальных счетов"; break;
caseTRADE_RETCODE_LIMIT_ORDERS: str="Достигнут лимит на количество отложенных ордеров"; break;
caseTRADE_RETCODE_LIMIT_VOLUME: str="Достигнут лимит на объем ордеров и позиций для данного символа"; break;
default: str="Неизвестный результат";
}
//---- return(str);
}
double NLot(string name,double dlot){
double stepLot=SymbolInfoDouble(name,SYMBOL_VOLUME_STEP);
return (MathFloor(dlot/stepLot)*stepLot);
}
bool time_check(string timeList){
//разделим строку на подстроки (разделитель , )ushort usep1=StringGetCharacter(",",0);
ushort usep2=StringGetCharacter("-",0);
ushort usep3=StringGetCharacter(":",0);
string param[],param2[],param3[],param4[];
long start_hour=0,start_minute=0,start_seconds=0;
long end_hour=0,end_minute=0,end_seconds=0;
datetime start_tm=0,end_tm=0,tm[];
ArrayInitialize(tm,0);
ArraySetAsSeries(tm,true);
CopyTime(_Symbol,PERIOD_D1,0,2,tm);
MqlDateTime dt={0};
TimeToStruct(TimeCurrent(),dt);
int c=StringSplit(timeList,usep1,param);
if(c<0) return (true);//диапозон не задан, можно торговать весь деньfor(int i=0;i<c;i++){
StringTrimRight(param[i]);
StringTrimLeft(param[i]);
if(StringSplit(param[i],usep2,param2)==2){
StringTrimRight(param2[0]);
StringTrimLeft(param2[0]);
StringTrimRight(param2[1]);
StringTrimLeft(param2[1]);
//удалили возможные лишние пробелы, теперь у нас есть время начала и окончания//разделим на чч.мм.ссif(StringSplit(param2[0],usep3,param3)>=1){
//время начала
start_hour=StringToInteger(param3[0]);
if(ArraySize(param3)>=2) start_minute=StringToInteger(param3[1]);
if(ArraySize(param3)==3) start_seconds=StringToInteger(param3[2]);
}
if(StringSplit(param2[1],usep3,param4)>=1){
//время окончания
end_hour=StringToInteger(param4[0]);
if(ArraySize(param4)>=2) end_minute=StringToInteger(param4[1]);
if(ArraySize(param4)==3) end_seconds=StringToInteger(param4[2]);
}
if(start_hour<=end_hour){
start_tm=(datetime)(tm[0]+start_hour*3600+start_minute*60+start_seconds);
end_tm=(datetime)(tm[0]+end_hour*3600+end_minute*60+end_seconds);
}else{
if(dt.hour>=0 && dt.hour<start_hour){
start_tm=(datetime)(tm[1]+start_hour*3600+start_minute*60+start_seconds);
end_tm=(datetime)(tm[0]+end_hour*3600+end_minute*60+end_seconds);
}
if(dt.hour>0 && dt.hour>=start_hour){
start_tm=(datetime)(tm[0]+start_hour*3600+start_minute*60+start_seconds);
end_tm=(datetime)(tm[0]+24*3600+end_hour*3600+end_minute*60+end_seconds);
}
}
if(TimeCurrent()>=start_tm && TimeCurrent()<=end_tm) return (true);
}
}
return (false);
}
voidOnTrade(){
if(semafor>0){
PrintFormat("Открыт ордер %d",semafor);
semafor=0; //сбросим семафор, операция с ордером завершаена, можно открывать следующий ордер
}
}
Talvez isto seja um bug) Ao iniciar o MT5, ao contrário do MT4, ao iniciar sem ligação a um servidor, a última autorização (login/password) não é carregada por alguma razão e precisa de ser autorizada novamente, a password e o login não são guardados neste caso. Qual poderá ser o problema?
É isto que a técnica chegou a- diferentes lucros ao mesmo tempo na mesma conta (era um dia de folga, cotações, preços de entrada, swaps - coincidem, só que o lucro não coincide)
A única diferença é que na primeira imagem o terminal está ligado através de senha de investimento e a optimização está em execução; a segunda imagem mostra o login através de senha comercial. E mesmo depois de reiniciar e actualizar o terminal, tudo permaneceu na mesma. Quando as cotações chegaram, tudo parecia normalizado
Foi a isto que a técnica chegou - lucros diferentes ao mesmo tempo na mesma conta (foi um dia de folga, cotações, preços de entrada, swaps - coincidem, só que o lucro não coincide)
A única diferença é que na primeira imagem o terminal está ligado através de senha de investimento e a optimização está em execução; a segunda imagem mostra o login através de senha comercial. E mesmo depois de reiniciar e actualizar o terminal, tudo permaneceu na mesma. Quando as cotações chegaram, tudo parecia normalizado
Aparentemente, as taxas cruzadasdisponíveis para o terminal para o cálculo do lucro flutuante eram diferentes.
Rosh: Aparentemente, as taxas cruzadas à disposição do terminal para o cálculo dos lucros flutuantes eram diferentes.
Aconteceu-me uma vez e pode não voltar a acontecer. Ou seja, não é de todo crítico. É por isso que não escrevi para o Service Desk. Só quero que saiba que o procedimento de cálculo do lucro/perda não é perfeito (por que são as taxas cruzadas diferentes, por exemplo?).
Transmitir parâmetros de entrada diferentes. Símbolo, ponto, parâmetros de entrada são os mesmos, o indicador é o mesmo. O terminal tenta minimizar o consumo de recursos e, neste caso, não é criada uma nova cópia do indicador, ou seja, um programa de mql5 funciona de facto.
Compreendo e lembro-me sobre a optimização do consumo de recursos, mas talvez juntamente com o símbolo, ponto, parâmetros de entrada devêssemos também verificar o nome curto do indicador? Se o programador definir claramente um nome curto único, ele compreende o que está a fazer, e precisa de uma cópia separada, mesmo que este indicador já exista no gráfico. Por exemplo, o indicador não tem quaisquer dados introduzidos, calcula automaticamente todos os dados iniciais na fase inicial, mas temos de forçar o utilizador a introduzir um parâmetro falso e lembrá-lo para não o introduzir noutro parâmetro.
Transmitir parâmetros de entrada diferentes. Símbolo, período, parâmetros de entrada são os mesmos, indicador é o mesmo. O terminal tenta minimizar o consumo de recursos e, neste caso, não é criada uma nova cópia do indicador, ou seja, funciona efectivamente um programa mql5.
Por favor aconselhe também sobre esta simples questão: https://www.mql5.com/ru/forum/1111/page975#comment_469324 , porque ninguém sabe. )))
Por favor, ajude-me a corrigi-lo. No Testador de Estratégia tudo funciona perfeitamente, mas na demonstração RTS em m1 por vezes em vez de uma posição de 3 lotes envia 2 encomendas de 3 lotes cada, e a posição total de 6 lotes.
É isto que a técnica chegou a
- diferentes lucros ao mesmo tempo na mesma conta (era um dia de folga, cotações, preços de entrada, swaps - coincidem, só que o lucro não coincide)
A única diferença é que na primeira imagem o terminal está ligado através de senha de investimento e a optimização está em execução; a segunda imagem mostra o login através de senha comercial. E mesmo depois de reiniciar e actualizar o terminal, tudo permaneceu na mesma. Quando as cotações chegaram, tudo parecia normalizado
Foi a isto que a técnica chegou - lucros diferentes ao mesmo tempo na mesma conta (foi um dia de folga, cotações, preços de entrada, swaps - coincidem, só que o lucro não coincide)
A única diferença é que na primeira imagem o terminal está ligado através de senha de investimento e a optimização está em execução; a segunda imagem mostra o login através de senha comercial. E mesmo depois de reiniciar e actualizar o terminal, tudo permaneceu na mesma. Quando as cotações chegaram, tudo parecia normalizado
Aparentemente, as taxas cruzadas à disposição do terminal para o cálculo dos lucros flutuantes eram diferentes.
A cada dois minutos envia este "conjunto" de erros sobre o Sinal de Negociação. Como repará-lo?
Transmitir parâmetros de entrada diferentes. Símbolo, ponto, parâmetros de entrada são os mesmos, o indicador é o mesmo. O terminal tenta minimizar o consumo de recursos e, neste caso, não é criada uma nova cópia do indicador, ou seja, um programa de mql5 funciona de facto.