그건 그렇고, 나는 중첩이 2 단계 이상일 때 매우 긴장합니다. 나는 절대 이런 식으로 쓰지 않으려고 하고, 코드를 함수 위에 퍼뜨립니다.
그리고 두 수준의 중첩이 있는 경우에도(항상 각 닫는 대괄호 뒤에) 어떤 블록이 묻어 있는지에 대한 설명을 작성합니다(예: 순환 제목을 복제함).
스타일과 관련하여 다음은 MT5의 역사적 위치 를 선택하는 코드입니다(지정된 날짜 범위의 지정된 매직, 기호로).
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());
};
동시에 히스토리 클래스 자체는 추상 인터페이스 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 ;
};
필요한 이력을 선택하면 해당 구성 요소(MT5의 경우 위치 또는 MT4의 경우 주문)를 다시 계산하고 추상 인터페이스 형태의 구성 요소에 대한 인터페이스를 얻을 수 있습니다.
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 ;
};
MT4의 경우 - 이러한 인터페이스에서 상속되는 해당 히스토리 클래스가 있습니다. 따라서 크로스 플랫폼도 제공됩니다. 어드바이저는 작동 위치를 전혀 찾을 필요가 없으며, 히스토리에 대한 모든 작업은 추상 인터페이스를 통해 수행됩니다.
Alexey Navoykov : 이 함수들은 바뀌지 않는데 왜 거기에 불필요한 중괄호를 잔뜩 넣었을까? 그것들을 제거하면 모든 것이 저절로 줄어들 것입니다. 그렇지 않으면 당신의 예가 우스꽝스러워 보입니다. 당신 자신이 코드를 닦은 다음 그것을 줄이기 위해 목발을 발명합니다.
동의합니다. 3줄을 더 자르고 코드를 단축할 수 있지만 목표는 사용할 코드를 배치하는 것이 아니라 실제로는 제 것도 아닙니다. 그러나 단축하기 위해 이러한 기능 5개를 하나에 넣을 수 있습니다. 하나가 아닌 화면. 그 후에 프로그램을 읽기가 더 쉬워지고 150번 스크롤할 필요가 없습니다. 그리고 파일의 크기가 줄어듭니다.
잘했어, 나는 그것을 좋아하지만 나는 OOP를 좋아하지 않고 OOP 없이 하려고 노력한다. 스레드가 분리된 프로세서를 좋아하지 않는 것처럼(예: 4개 코어 및 8개 스레드). 커널의 스레드 분할이든 코드의 기능 가상화이든 분할 및 가상화는 성능 손실 및 구현을 위한 기계 시간 손실이라는 것이 분명해야 합니다.
비탈리 무지첸코 :
동의합니다. 3줄을 더 자르고 코드를 단축할 수 있지만 목표는 사용할 코드를 배치하는 것이 아니라 실제로는 제 것도 아닙니다. 그러나 단축하기 위해 이러한 기능 5개를 하나에 넣을 수 있습니다. 하나가 아닌 화면. 그 후에 프로그램을 읽기가 더 쉬워지고 150번 스크롤할 필요가 없습니다. 그리고 파일의 크기가 줄어듭니다.
카운터 질문)) MyFunc.mqh 파일에 그런 기능이 있는데 압축할 이유가 조금도 없습니다. 디스크에 10-20Kb를 저장해야 하는 이유는 무엇입니까? 그리고 솔직히 이 코드 스타일은 기분이 나쁩니다))
그 사람은 "나는 모든 것을 나에게 가지고 간다"는 원칙을 가지고 있다고 썼습니다. 고문의 전체 코드는 하나의 파일에 채워질 것입니다. 따라서 그는 이러한 모든 기능을 복사하여 각 고문에 붙여넣습니다. 따라서 개수: 1000 Expert Advisors x 10kb = 10Mb - 이미 절약에 대해 생각할 이유가 있음))
카운터 질문)) MyFunc.mqh 파일에 그런 기능이 있는데 압축할 이유가 조금도 없습니다. 디스크에 10-20Kb를 저장해야 하는 이유는 무엇입니까? 그리고 솔직히 이 코드 스타일 은 기분이 나쁩니다 ))
저도 그렇지만 저는 오래전에 한 번도 보지 않은 곳에서 코드를 압축해야 한다는 결론에 도달했습니다.
포함된 사용자 정의 코드를 분산시키면 또 다른 골칫거리가 생깁니다 . 파일을 다른 터미널로 드래그 하거나 공유하려면 하나의 파일이 아니라 여러 파일을 드래그해야 합니다. 물론 내포물을 모든 단말로 옮길 수도 있지만, 하나의 단말에서 수정하거나 추가했다면 모두 새 단말로 교체해야 한다.
Expert Advisors와 지표는 너무 작아서 프로그램의 본체에서 무언가를 옮기는 것은 의미가 없습니다. 또는 오히려 작지 않고 단일 파일입니다. 이것은 클래스와 포함 없이는 할 수 없는 10,000페이지의 사이트가 아닙니다. 게다가, 이제 구조가 있고 100% 효율적인 간결한 코드를 작성하기에 충분합니다.
그런 다음 하단에 있는 4개의 괄호가 무엇을 의미하는지 눈으로 샅샅이 살펴보세요.
그건 그렇고, 나는 중첩이 2 단계 이상일 때 매우 긴장합니다. 나는 절대 이런 식으로 쓰지 않으려고 하고, 코드를 함수 위에 퍼뜨립니다.
그리고 두 수준의 중첩이 있는 경우에도(항상 각 닫는 대괄호 뒤에) 어떤 블록이 묻어 있는지에 대한 설명을 작성합니다(예: 순환 제목을 복제함).
스타일과 관련하여 다음은 MT5의 역사적 위치 를 선택하는 코드입니다(지정된 날짜 범위의 지정된 매직, 기호로).
동시에 히스토리 클래스 자체는 추상 인터페이스 CTradeHistoryI의 상속자입니다.
필요한 이력을 선택하면 해당 구성 요소(MT5의 경우 위치 또는 MT4의 경우 주문)를 다시 계산하고 추상 인터페이스 형태의 구성 요소에 대한 인터페이스를 얻을 수 있습니다.
MT4의 경우 - 이러한 인터페이스에서 상속되는 해당 히스토리 클래스가 있습니다. 따라서 크로스 플랫폼도 제공됩니다. 어드바이저는 작동 위치를 전혀 찾을 필요가 없으며, 히스토리에 대한 모든 작업은 추상 인터페이스를 통해 수행됩니다.
항상 일정하고 이 스타일로 절대 변경되지 않는 함수를 작성하지 마십시오.
간결하게 쓰세요. 어쨌든 아무도 쳐다보지도 않고 줄도 절반만 씁니다.
이 함수들은 바뀌지 않는데 왜 거기에 불필요한 중괄호를 잔뜩 넣었을까? 그것들을 제거하면 모든 것이 저절로 줄어들 것입니다. 그렇지 않으면 당신의 예가 우스꽝스러워 보입니다. 당신 자신이 코드를 닦은 다음 그것을 줄이기 위해 목발을 발명합니다.
동의합니다. 3줄을 더 자르고 코드를 단축할 수 있지만 목표는 사용할 코드를 배치하는 것이 아니라 실제로는 제 것도 아닙니다. 그러나 단축하기 위해 이러한 기능 5개를 하나에 넣을 수 있습니다. 하나가 아닌 화면. 그 후에 프로그램을 읽기가 더 쉬워지고 150번 스크롤할 필요가 없습니다. 그리고 파일의 크기가 줄어듭니다.
잘했어, 나는 그것을 좋아하지만 나는 OOP를 좋아하지 않고 OOP 없이 하려고 노력한다. 스레드가 분리된 프로세서를 좋아하지 않는 것처럼(예: 4개 코어 및 8개 스레드). 커널의 스레드 분할이든 코드의 기능 가상화이든 분할 및 가상화는 성능 손실 및 구현을 위한 기계 시간 손실이라는 것이 분명해야 합니다.
동의합니다. 3줄을 더 자르고 코드를 단축할 수 있지만 목표는 사용할 코드를 배치하는 것이 아니라 실제로는 제 것도 아닙니다. 그러나 단축하기 위해 이러한 기능 5개를 하나에 넣을 수 있습니다. 하나가 아닌 화면. 그 후에 프로그램을 읽기가 더 쉬워지고 150번 스크롤할 필요가 없습니다. 그리고 파일의 크기가 줄어듭니다.
감사합니다.
작업 화면 27"
나는 게시물을 다시 읽지 않을 것이며 인용할 것입니다: " 항상 일정하고 이 스타일로 절대 변경되지 않는 함수를 작성하지 마십시오 "
플랫폼이 출시되면 한 번 작성되고 앞으로도 변경되지 않는 기능에 왜 눈을 찔러야 합니까? 로트 크기, 주문 수 , 일반 주문을 가져오는 함수에서 코드를 자주 변경/편집합니까? 그렇다면 32인치 모니터의 3개 화면에 걸쳐 확장하는 이유는 무엇입니까?
추신: 코드가 첨부되어 있으며, 코드 베이스에서 발췌했습니다.
카운터 질문)) MyFunc.mqh 파일에 그런 기능이 있는데 압축할 이유가 조금도 없습니다. 디스크에 10-20Kb를 저장해야 하는 이유는 무엇입니까? 그리고 솔직히 이 코드 스타일은 기분이 나쁩니다))
카운터 질문)) MyFunc.mqh 파일에 그런 기능이 있는데 압축할 이유가 조금도 없습니다. 디스크에 10-20Kb를 저장해야 하는 이유는 무엇입니까? 그리고 솔직히 이 코드 스타일은 기분이 나쁩니다))
저에게 코드는 이해하기 쉽고, 짧고, 빠르게 작동해야 하며, 어떤 조건에서도 오류 없이 작동해야 합니다.
감사합니다.
카운터 질문)) MyFunc.mqh 파일에 그런 기능이 있는데 압축할 이유가 조금도 없습니다. 디스크에 10-20Kb를 저장해야 하는 이유는 무엇입니까? 그리고 솔직히 이 코드 스타일은 기분이 나쁩니다))
따라서 개수: 1000 Expert Advisors x 10kb = 10Mb - 이미 절약에 대해 생각할 이유가 있음))
카운터 질문)) MyFunc.mqh 파일에 그런 기능이 있는데 압축할 이유가 조금도 없습니다. 디스크에 10-20Kb를 저장해야 하는 이유는 무엇입니까? 그리고 솔직히 이 코드 스타일 은 기분이 나쁩니다 ))
저도 그렇지만 저는 오래전에 한 번도 보지 않은 곳에서 코드를 압축해야 한다는 결론에 도달했습니다.
포함된 사용자 정의 코드를 분산시키면 또 다른 골칫거리가 생깁니다 . 파일을 다른 터미널로 드래그 하거나 공유하려면 하나의 파일이 아니라 여러 파일을 드래그해야 합니다. 물론 내포물을 모든 단말로 옮길 수도 있지만, 하나의 단말에서 수정하거나 추가했다면 모두 새 단말로 교체해야 한다.
Expert Advisors와 지표는 너무 작아서 프로그램의 본체에서 무언가를 옮기는 것은 의미가 없습니다. 또는 오히려 작지 않고 단일 파일입니다. 이것은 클래스와 포함 없이는 할 수 없는 10,000페이지의 사이트가 아닙니다. 게다가, 이제 구조가 있고 100% 효율적인 간결한 코드를 작성하기에 충분합니다.
그건 그렇고, 나는 중첩이 2 단계 이상일 때 매우 긴장합니다. 나는 절대 이런 식으로 쓰지 않으려고 하고, 코드를 함수 위에 퍼뜨립니다.
그리고 두 수준의 중첩이 있는 경우에도(항상 각 닫는 대괄호 뒤에) 어떤 블록이 묻어 있는지에 대한 설명을 작성합니다(예: 순환 제목을 복제함).
스타일과 관련하여 다음은 MT5의 역사적 위치 를 선택하는 코드입니다(지정된 날짜 범위의 지정된 매직, 기호로).
동시에 히스토리 클래스 자체는 추상 인터페이스 CTradeHistoryI의 상속자입니다.
필요한 이력을 선택하면 해당 구성 요소(MT5의 경우 위치 또는 MT4의 경우 주문)를 다시 계산하고 추상 인터페이스 형태의 구성 요소에 대한 인터페이스를 얻을 수 있습니다.
MT4의 경우 - 이러한 인터페이스에서 상속되는 해당 히스토리 클래스가 있습니다. 따라서 크로스 플랫폼도 제공됩니다. 어드바이저는 작동 위치를 전혀 찾을 필요가 없으며, 히스토리에 대한 모든 작업은 추상 인터페이스를 통해 수행됩니다.
맛있어 보이는데 TRACE_***와 ASSERT도 볼 수 있나요?
파일을 다른 터미널로 드래그 하거나 공유하려면 한 파일이 아닌 여러 파일을 드래그해야 합니다. 물론 내포물을 모든 단말로 옮길 수 있지만, 하나의 단말에서 수정하거나 추가했다면 모두 새 단말로 교체해야 한다.