E então você tem que olhar para cima o que esses quatro colchetes na parte inferior se referem.
A propósito, fico muito nervoso quando o ninho é mais de dois níveis. Tento nunca escrevê-lo dessa maneira, espalhando o código sobre as funções.
E mesmo quando há dois níveis de encaixe - não deixe de escrever comentários após cada colchete de fechamento - que bloqueiam o encaixe (digamos, cabeçalho de laço duplicado).
Quanto ao estilo, aqui está meu código para selecionaruma posição histórica para MT5 (por um mágico especificado, símbolo, com um intervalo de datas especificado):
int CMT5TradeHistory::Select(ulong ulMagic,ECurrencySymbol csSymbol,datetime dtFrom = MIN_DATETIME,datetime dtTill = NEVER_EXPIRES)
{
ASSERT(dtFrom <= dtTill);
// Очистим список ядер позиции
m_aoPosCores.Clear();
// Запросим историю ордеров и сделокif(HistorySelect(dtFrom,dtTill)!=true)
return(WRONG_VALUE);
// Соберем тикеты исторических позиций// Просмотрим все сделки выхода, и выпишем оттуда тикеты позиций.int iHistoryDealsTotal=HistoryDealsTotal();
CArrayLong alHistoryPosIDs;
int iI = WRONG_VALUE;
ulong ulCurTicket = 0;
long lCurPosID = 0;
long lCurMagic = 0;
long lCurEntry = 0;
string strCurSymbol;
for(iI=0;iI<iHistoryDealsTotal; ++iI)
{
ulCurTicket = HistoryDealGetTicket(iI);
if(ulCurTicket == 0)
return(WRONG_VALUE);
// Получим направление сделки if(HistoryDealGetInteger(ulCurTicket,DEAL_ENTRY,lCurEntry)!=true)
{
TRACE_INTEGER("Не удалось получить направление сделки ! Тикет: ",ulCurTicket);
continue;
};
// Проверим направление сделкиif(lCurEntry != DEAL_ENTRY_OUT)
continue;
// Получим магик сделкиif(HistoryDealGetInteger(ulCurTicket,DEAL_MAGIC,lCurMagic)!=true)
{
TRACE_INTEGER("Не удалось получить магик сделки ! Тикет: ",ulCurTicket);
continue;
};
// Проверим магикif(ulMagic != NULL && lCurMagic != ulMagic)
{
//TRACE_INTEGER("Сделка не подходит ! Имеет неверный магик ! Magic сделки: ",lCurMagic);//TRACE_INTEGER("Требуемый Magic : ",ulMagic);continue;
};
// Получим символ сделкиif(HistoryDealGetString(ulCurTicket,DEAL_SYMBOL,strCurSymbol)!=true)
{
TRACE_INTEGER("Не удалось получить символ ордера ! Тикет: ",ulCurTicket);
continue;
};
// Проверим символif(csSymbol != CS_UNKNOWN)
if(csSymbol == CS_CURRENT)
{
if(_Symbol2CurrencyEnum(strCurSymbol) != _Symbol2CurrencyEnum(Symbol()))
{
//TRACE2("Symbol выбираемой позиции: ",_Enum2CurrencySymbol(csSymbol));//TRACE2("Выбранный ордер имеет неверный символ: ",strCurSymbol);continue;
};
}
else
{
if(_Symbol2CurrencyEnum(strCurSymbol) != csSymbol)
{
//TRACE2("Symbol выбираемой позиции: ",_Enum2CurrencySymbol(csSymbol));//TRACE2("Выбранный ордер имеет неверный символ ! Символ ордера: ",poiBuffer.GetSymbolString());continue;
};
};
// Получим ID позицииif(HistoryDealGetInteger(ulCurTicket,DEAL_POSITION_ID,lCurPosID)!=true)
{
TRACE_INTEGER("Не удалось получить ID позиции ! Тикет: ",ulCurTicket);
continue;
};
// Проверим ID позицииif(lCurPosID <= NULL)
continue;
if(alHistoryPosIDs.Add(lCurPosID)!=true)
return(WRONG_VALUE);
}; // цикл перебора всех сделок// Здесь ID всех позиций собраны в массиве alHistoryPosIDs, необходимо убрать повторения (в позиции может быть много ордеров)
CArrayLong alUnicalHistoryPosIDs;
if(_DeleteDoubles(GetPointer(alHistoryPosIDs),GetPointer(alUnicalHistoryPosIDs))!=true)
return(WRONG_VALUE);
TRACE_INTEGER("Уникальных ID позиций в истории: ",alUnicalHistoryPosIDs.Total());
// Здесь массив alUnicalHistoryPosIDs заполнен уникальными ID позиций в истории.// Заполним ядра позиции
CMT5HistoryPositionInfoCore* phpiHistPosCore = NULL;
for(iI=0;iI<alUnicalHistoryPosIDs.Total(); ++iI)
{
//TRACE_INTEGER("Выберем позицию: ",iI);// Выберем очередной тикет
lCurPosID = alUnicalHistoryPosIDs.At(iI);
// Позиция является нужной компонентой
ASSERT(phpiHistPosCore == NULL);
phpiHistPosCore = new CMT5HistoryPositionInfoCore;
if(phpiHistPosCore == NULL)
{
m_aoPosCores.Clear();
ASSERT_DSC(false,"Не удалось создать объект CMT5HistoryPositionInfoCore по new");
return(WRONG_VALUE);
};
ASSERT_MYPOINTER(phpiHistPosCore);
if(phpiHistPosCore.SelectByID(lCurPosID)!=true)
{
TRACE("Не удалось создать выбрать позицию ! Возможно, позиция открыта, и еще не полностью в истории.");
TRACE_INTEGER("ID невыбранной позиции: ",lCurPosID);
delete phpiHistPosCore;
phpiHistPosCore = NULL;
continue;
};
ASSERT(phpiHistPosCore.GetTPCOpenTime() > MIN_DATETIME && phpiHistPosCore.GetTPCOpenTime() < phpiHistPosCore.GetTPCCloseTime() && phpiHistPosCore.GetTPCCloseTime() < NEVER_EXPIRES);
// Найдена и выбрана еще одна компонента позицииif(m_aoPosCores.Add(phpiHistPosCore) == false)
{
delete phpiHistPosCore;
m_aoPosCores.Clear();
ASSERT_DSC(false,"Не удалось добавить новый объект в список ядер позиции");
return(WRONG_VALUE);
};
phpiHistPosCore = NULL;
}; // цикл перебора уникальных PosID// TRACE_INTEGER("Ядер в выбранной позиции: ",m_aoPosCores.Total()); return(m_aoPosCores.Total());
};
A própria classe de história é descendente da interface abstrata CTradeHistoryI:
class CTradeHistoryI: public CMyObject
{
public:
void CTradeHistoryI() { SetMyObjectType(MOT_TRADE_HISTORY_I); };
virtualvoid ~CTradeHistoryI() {};
// Выбор существующей истории. // Указывается магик и символ, по которому выбираются исторические ордера, а также промежуток времени, в котором необходимо искать их.// Если ulMagic = 0 - выбираются все позиции по всем магикам.// Если ECurrencySymbol = CS_UNKNOWN - выбираются все позиции по всем символам// Если ECurrencySymbol = CS_CURRENT - запрашивается функция Symbol(), и выбираются все позиции по этому символу// Возвращает число компонент позиции внутри истории (может быть нулевым если ничего не найдено) или WRONG_VALUE в случае ошибок// NOTE !!! // При выборе - отложенные ордера не учитываются.virtualint Select(ulong ulMagic = 0,ECurrencySymbol csSymbol = CS_CURRENT,datetime dtFrom = MIN_DATETIME,datetime dtTill = NEVER_EXPIRES) = 0;
virtualuint GetTotalComponents() const = 0; // Получение общего числа компонентvirtual CHistoryPosComponentI* GetComponent(uint uiComponentIdx) const = 0;
// Расширенный интерфейсvirtualvoid Sort(ESortTPCMode stmMode = STM_BY_OPEN_TIME_A) = 0;
// Функция ищет внутри истории компоненту с указанным тикетом. // В случае, если ее нет - возвращается false.// Если компонента найдена - возвращается true, и uiComponentIdx устанавливается на индекс компоненты внутри позиции.virtualbool FindComponentByTicket(long lTicket,uint &uiComponentIdx) const = 0;
};
Ao selecionar o histórico necessário - você pode recalcular seus componentes (posições para MT5 ou pedidos para MT4), e obter uma interface para qualquer componente como uma interface abstrata:
class CTradePosComponentI: public CMyObject
{
public:
void CTradePosComponentI() { SetMyObjectType(MOT_TRADEPOS_COMPONENT_I); };
virtualvoid ~CTradePosComponentI() {};
// Основной интерфейсvirtuallong GetTPCTicket() const = 0;
virtuallong GetTPCMagic() const = 0;
virtual ECurrencySymbol GetTPCSymbol() const = 0;
virtualENUM_POSITION_TYPE GetTPCType() const = 0;
virtualdatetime GetTPCOpenTime() const = 0;
virtualdouble GetTPCVolume() const = 0;
virtualdouble GetTPCOpenPrice() const = 0;
virtualdouble GetTPCStopLoss() const = 0;
virtualdouble GetTPCTakeProfit() const = 0;
virtualstring GetTPCCommentary() const = 0;
virtualbool IsTPCInUnloss() const { if(GetTPCStopLoss() <= 0 || GetTPCStopLoss() == EMPTY_VALUE) return(false); if(GetTPCType() == POSITION_TYPE_BUY) { if(GetTPCStopLoss() >= GetTPCOpenPrice()) return(true); } else { if(GetTPCStopLoss() <= GetTPCOpenPrice())return(true); }; return (false); };
virtualdouble GetTPDistance() const { if(GetTPCTakeProfit() == 0 || GetTPCTakeProfit() == EMPTY_VALUE) return(EMPTY_VALUE); if(GetTPCType() == POSITION_TYPE_BUY) return(GetTPCTakeProfit() - GetTPCOpenPrice()); return(GetTPCOpenPrice() - GetTPCTakeProfit()); };
virtualdouble GetSLDistance() const { if(GetTPCStopLoss() == 0 || GetTPCStopLoss() == EMPTY_VALUE) return(EMPTY_VALUE); if(GetTPCType() == POSITION_TYPE_BUY) return(GetTPCOpenPrice()- GetTPCStopLoss()); return(GetTPCStopLoss() - GetTPCOpenPrice()); };
};
class CHistoryPosComponentI: public CTradePosComponentI
{
public:
void CHistoryPosComponentI() { SetMyObjectType(MOT_HISTORYPOS_COMPONENT_I); };
virtualvoid ~CHistoryPosComponentI() {};
virtualdatetime GetTPCCloseTime() const = 0;
virtualdouble GetTPCClosePrice() const = 0;
virtualdouble GetTPCProfit() const = 0; // Возвращает профит по исторической позицииvirtualbool IsProfitClosePrice() const = 0; // Возвращает true, если цена зарытия отличается от цены открытия в прибыльную сторону // Возвращает профит исторической позиции для случая, когда бы ход цены (в сторону профита) был бы равен dPriceMove, а лот был бы единичным.// Функция используется для расчета лота для такой же позиции с нужным ходом цены // Рекомендуется отнимать от цены двойной спред.virtualdouble CalculateOneLotProfit(double dPriceMove) const = 0;
};
Para o MT4 - há classes de história correspondentes também herdadas dessas interfaces - assim, ao mesmo tempo, a cross-platformidade é fornecida - uma EA não precisa descobrir onde trabalha, todo o trabalho com a história é feito através das interfaces abstratas.
Não escreva funções que são sempre constantes e nunca mudam neste estilo
Escreva-os concisamente, ninguém nunca olha para eles de qualquer maneira, e eles pegam metade das linhas
Uma vez que estas funções nunca mudam, por que você coloca um monte de parênteses desnecessários? Remova-os e tudo encolherá por si só. Porque o seu exemplo parece absurdo: você mesmo desfocou o código e depois inventou muletas para reduzi-lo.
Alexey Navoykov: Como estas funções não mudam, por que você colocou um monte de parênteses desnecessários? Removê-los, e tudo será comprimido. Porque o seu exemplo parece absurdo: você mesmo desfocou o código e depois inventou muletas para reduzi-lo.
Concordo, você pode cortar mais 3 linhas e encurtar o código, mas o objetivo não era colocar o código para usar, na verdade ele não é nem meu, mas para encurtar, e tais funções podem ser colocadas cinco em uma tela, não uma. Depois disso, os programas são mais fáceis de ler e você não precisa rolar 150 vezes. E o peso do arquivo diminui.
Bom trabalho, eu gosto, mas não gosto do OOP e tento fazer sem ele. Não gosto de processadores com divisão de thread (por exemplo, 4 núcleos e 8 threads). Deve ficar claro que a divisão e qualquer virtualização é uma perda de performance e perda de tempo de máquina para sua implementação, seja ela divisão de thread no kernel ou virtualização de funções no código.
Vitaly Muzichenko:
Concordo, você pode cortar mais 3 linhas, e encurtar o código, mas o objetivo não era colocar o código para usar, ele nem é meu de fato, mas encurtá-lo, e você pode colocar cinco dessas funções em uma tela, não uma. Depois disso, os programas são mais fáceis de ler e você não precisa rolar 150 vezes. E o peso do arquivo é reduzido.
Não vou relê-la, vou apenas citá-la:"Não escreva funções que são sempre constantes e nunca mudam nesse estilo"
Por que escolher seus olhos sobre uma função que é escrita uma vez quando a plataforma é liberada e nunca mudará no futuro? Você costuma mudar/editar o código nas funções para obter tamanho de lote, número de pedidos e típico? Então por que esticá-lo através de 3 telas de um monitor de 32"?
P.S. O código anexo é forjado a partir do kodobase.
Pergunta contrária )))) Tenho tais funções no arquivo MyFunc.mqh, não vejo o menor sentido em comprimi-lo. Por que, para economizar 10-20 KB em disco? E francamente falando, tal codestream me deixa doente ))
Pergunta contrária )))) Eu tenho tais funções no arquivo MyFunc.mqh, não vejo o menor sentido em comprimir isto. Por que, para economizar 10-20 KB em disco? Para ser honesto, este codestream me deixa doente )).
Eu também uso incluir arquivos, é conveniente. Especialmente quando você escreve um roteiro personalizado, muitas funções são as mesmas e é bobagem escrever uma e a mesma coisa, basta incluir o arquivo e a função está em seu EA. Quanto a mim, o código deve ser claro, curto, rápido para trabalhar e deve funcionar em todas as condições sem erros.
Pergunta contrária )))) Eu tenho tais funções no arquivo MyFunc.mqh, não vejo o menor sentido em comprimir isto. Por que, para economizar 10-20 KB em disco? E francamente falando, tal codestream me deixa doente ))
O programador escreveu que o princípio "eu mesmo carrego tudo"; todo o código do Expert Advisor está amontoado em um único arquivo. Assim, ele copia todas essas funções em cada EA. Então, conte: 1000 EAs x 10 Kb = 10 Mb - você já tem que pensar em economizar ))
Pergunta contrária )))) Eu tenho tais funções no arquivo MyFunc.mqh, não vejo o menor sentido em comprimir isto. Por que, para economizar 10-20 KB em disco? E francamente falando, tal codestream me deixa doente ))
Eu também, mas há muito tempo cheguei à conclusão de que o código deve ser compacto em lugares onde nunca se olha para ele, onde ele nunca é corrigido e nunca será corrigido.
Espalhar o código do usuário com todos os inlúdios é uma dor de cabeça adicional, quando você precisa arrastar e soltar um arquivo em outro terminal, ou compartilhá-lo, você precisará arrastar e soltar vários arquivos. É claro que você pode transferir os incluídos para todos os terminais, mas se você mudar ou acrescentar algo em um terminal, então todos eles devem ser substituídos por um novo.
Os Conselheiros Especialistas e os indicadores são tão pequenos que não adianta afastá-los do corpo do programa. Para ser mais correto, eles não são pequenos, são um único arquivo, não é como um site com 10 000 páginas onde não se pode prescindir de aulas e inlúdios. Além disso, agora existem estruturas, e elas são suficientes para escrever um código compacto e 100% funcional.
A propósito, fico muito nervoso quando o ninho é mais de dois níveis. Tento nunca escrevê-lo dessa maneira, espalhando o código sobre as funções.
E mesmo quando há dois níveis de aninhamento - não deixe de escrever comentários após cada parêntese de fechamento, que bloqueiam o enterramento (digamos, cabeçalho de laço duplicado).
Quanto ao estilo, aqui está meu código para selecionar aposição do histórico para MT5 (por magik especificado, símbolo, com intervalo de datas especificado):
A própria classe de história é descendente da interface abstrata CTradeHistoryI:
Ao selecionar o histórico necessário - você pode recalcular seus componentes (posições para MT5 ou pedidos para MT4), e obter uma interface para qualquer componente como uma interface abstrata:
Para o MT4 existem classes de história correspondentes que também herdam destas interfaces - assim, ao mesmo tempo em que a plataforma cruzada é fornecida - o Expert Advisor não precisa descobrir onde trabalha, todo o trabalho com a história é feito através de interfaces abstratas.
Parece bom, podemos também olhar para TRACE_**** e ASSERT?
Para arrastar e soltar um arquivo para outro terminal, ou para compartilhá-lo, você precisa arrastar não apenas um arquivo, mas vários. Você pode, é claro, transferir os nódulos para todos os terminais, mas se você mudar ou acrescentar algo em um terminal, então você precisa substituí-lo por um novo em todos os terminais.
Recomendo o uso de links simbólicos ou links de junção para a pasta de MQL. Todos os terminais procurarão em uma pasta.
Para login e uso do site MQL5.com, você deve ativar o uso de cookies.
Ative esta opção no seu navegador, caso contrário você não poderá fazer login.
Você entrou na conta. A autenticação de dois fatores foi desativada. Configure-a novamente e escaneie um novo código QR ou continue com a autenticação de dois fatores desativada.
E então você tem que olhar para cima o que esses quatro colchetes na parte inferior se referem.
A propósito, fico muito nervoso quando o ninho é mais de dois níveis. Tento nunca escrevê-lo dessa maneira, espalhando o código sobre as funções.
E mesmo quando há dois níveis de encaixe - não deixe de escrever comentários após cada colchete de fechamento - que bloqueiam o encaixe (digamos, cabeçalho de laço duplicado).
Quanto ao estilo, aqui está meu código para selecionaruma posição histórica para MT5 (por um mágico especificado, símbolo, com um intervalo de datas especificado):
A própria classe de história é descendente da interface abstrata CTradeHistoryI:
Ao selecionar o histórico necessário - você pode recalcular seus componentes (posições para MT5 ou pedidos para MT4), e obter uma interface para qualquer componente como uma interface abstrata:
Para o MT4 - há classes de história correspondentes também herdadas dessas interfaces - assim, ao mesmo tempo, a cross-platformidade é fornecida - uma EA não precisa descobrir onde trabalha, todo o trabalho com a história é feito através das interfaces abstratas.
Não escreva funções que são sempre constantes e nunca mudam neste estilo
Escreva-os concisamente, ninguém nunca olha para eles de qualquer maneira, e eles pegam metade das linhas
Como estas funções não mudam, por que você colocou um monte de parênteses desnecessários? Removê-los, e tudo será comprimido. Porque o seu exemplo parece absurdo: você mesmo desfocou o código e depois inventou muletas para reduzi-lo.
Concordo, você pode cortar mais 3 linhas e encurtar o código, mas o objetivo não era colocar o código para usar, na verdade ele não é nem meu, mas para encurtar, e tais funções podem ser colocadas cinco em uma tela, não uma. Depois disso, os programas são mais fáceis de ler e você não precisa rolar 150 vezes. E o peso do arquivo diminui.
Bom trabalho, eu gosto, mas não gosto do OOP e tento fazer sem ele. Não gosto de processadores com divisão de thread (por exemplo, 4 núcleos e 8 threads). Deve ficar claro que a divisão e qualquer virtualização é uma perda de performance e perda de tempo de máquina para sua implementação, seja ela divisão de thread no kernel ou virtualização de funções no código.
Concordo, você pode cortar mais 3 linhas, e encurtar o código, mas o objetivo não era colocar o código para usar, ele nem é meu de fato, mas encurtá-lo, e você pode colocar cinco dessas funções em uma tela, não uma. Depois disso, os programas são mais fáceis de ler e você não precisa rolar 150 vezes. E o peso do arquivo é reduzido.
Sinceramente.
Tela de trabalho de 27".
Não vou relê-la, vou apenas citá-la:"Não escreva funções que são sempre constantes e nunca mudam nesse estilo"
Por que escolher seus olhos sobre uma função que é escrita uma vez quando a plataforma é liberada e nunca mudará no futuro? Você costuma mudar/editar o código nas funções para obter tamanho de lote, número de pedidos e típico? Então por que esticá-lo através de 3 telas de um monitor de 32"?
P.S. O código anexo é forjado a partir do kodobase.
Pergunta contrária )))) Tenho tais funções no arquivo MyFunc.mqh, não vejo o menor sentido em comprimi-lo. Por que, para economizar 10-20 KB em disco? E francamente falando, tal codestream me deixa doente ))
Pergunta contrária )))) Eu tenho tais funções no arquivo MyFunc.mqh, não vejo o menor sentido em comprimir isto. Por que, para economizar 10-20 KB em disco? Para ser honesto, este codestream me deixa doente )).
Quanto a mim, o código deve ser claro, curto, rápido para trabalhar e deve funcionar em todas as condições sem erros.
Sinceramente.
Pergunta contrária )))) Eu tenho tais funções no arquivo MyFunc.mqh, não vejo o menor sentido em comprimir isto. Por que, para economizar 10-20 KB em disco? E francamente falando, tal codestream me deixa doente ))
Então, conte: 1000 EAs x 10 Kb = 10 Mb - você já tem que pensar em economizar ))
Pergunta contrária )))) Eu tenho tais funções no arquivo MyFunc.mqh, não vejo o menor sentido em comprimir isto. Por que, para economizar 10-20 KB em disco? E francamente falando, tal codestream me deixa doente ))
Eu também, mas há muito tempo cheguei à conclusão de que o código deve ser compacto em lugares onde nunca se olha para ele, onde ele nunca é corrigido e nunca será corrigido.
Espalhar o código do usuário com todos os inlúdios é uma dor de cabeça adicional, quando você precisa arrastar e soltar um arquivo em outro terminal, ou compartilhá-lo, você precisará arrastar e soltar vários arquivos. É claro que você pode transferir os incluídos para todos os terminais, mas se você mudar ou acrescentar algo em um terminal, então todos eles devem ser substituídos por um novo.
Os Conselheiros Especialistas e os indicadores são tão pequenos que não adianta afastá-los do corpo do programa. Para ser mais correto, eles não são pequenos, são um único arquivo, não é como um site com 10 000 páginas onde não se pode prescindir de aulas e inlúdios. Além disso, agora existem estruturas, e elas são suficientes para escrever um código compacto e 100% funcional.
A propósito, fico muito nervoso quando o ninho é mais de dois níveis. Tento nunca escrevê-lo dessa maneira, espalhando o código sobre as funções.
E mesmo quando há dois níveis de aninhamento - não deixe de escrever comentários após cada parêntese de fechamento, que bloqueiam o enterramento (digamos, cabeçalho de laço duplicado).
Quanto ao estilo, aqui está meu código para selecionar aposição do histórico para MT5 (por magik especificado, símbolo, com intervalo de datas especificado):
A própria classe de história é descendente da interface abstrata CTradeHistoryI:
Ao selecionar o histórico necessário - você pode recalcular seus componentes (posições para MT5 ou pedidos para MT4), e obter uma interface para qualquer componente como uma interface abstrata:
Para o MT4 existem classes de história correspondentes que também herdam destas interfaces - assim, ao mesmo tempo em que a plataforma cruzada é fornecida - o Expert Advisor não precisa descobrir onde trabalha, todo o trabalho com a história é feito através de interfaces abstratas.
Parece bom, podemos também olhar para TRACE_**** e ASSERT?
Para arrastar e soltar um arquivo para outro terminal, ou para compartilhá-lo, você precisa arrastar não apenas um arquivo, mas vários. Você pode, é claro, transferir os nódulos para todos os terminais, mas se você mudar ou acrescentar algo em um terminal, então você precisa substituí-lo por um novo em todos os terminais.