И потом ковыряйся глазами, к чему относятся эти 4 скобки внизу.
Кстати, меня очень нервирует, когда вложенность более двух уровней. Стараюсь так никогда не писать, раскидывая код по функциям.
И даже когда два уровня вложенности - обязательно после каждой закрывающей скобки - пишу комментарии, какой блок она зарывает (скажем, дублирую заголовок цикла).
Что касается стиля, то вот мой код выбора исторической позиции для МТ5 (по указанному магику, символу, с указанным диапазоном дат):
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;
};
Выбрав необходимую историю - можно пересчитать ее компоненты (позици для МТ5 или ордера для МТ4), и получить интерфейс на любую компоненту в виде абстрактного интерфейса:
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;
};
Для МТ4 - есть соответствующие классы истории, также наследующиеся от этих интерфейсов - таким образом, заодно обеспечивается и кропссплатформенность - советнику совершенно не надо выяснять, где он работает, вся работа с историей ведется через абстрактные интерфейсы.
Не писать функции которые всегда постоянны и никогда не изменяются в таком стиле
Пишите их сжато, всё-равно в них никогда никто не смотрит, а строк занимает в два раза меньше
Раз эти функции не меняются, то зачем вы там кучу ненужных фигурных скобок понаставили? Уберите их, и всё само сожмётся. А то ваш пример выглядит нелепо: сами же размазали код, а потом выдумываете костыли, чтобы его сократить.
Alexey Navoykov: Раз эти функции не меняются, то зачем вы там кучу ненужных фигурных скобок понаставили? Уберите их, и всё само сожмётся. А то ваш пример выглядит нелепо: сами же размазали код, а потом выдумываете костыли, чтобы его сократить.
Согласен, можно выпилить ещё 3 строки, и сократить код, но цель была не выложить код к использованию, он по сути даже не мой, а сократить, и таких функций можно поставить пять в один экран, а не одну. После этого программы читаются легче, и не нужно 150 раз скролить. И вес файла уменьшается.
хорошая работа, мне нравиться, но мне не нравиться ООП и стараюсь обходиться без него. как и не нравятся процессоры, с разделением потоков (пример 4 ядра и 8 потоков). должно быть понятно что разделение и любая виртуализация это потеря производительности и потеря машинного времени на ее осуществление, будь то разделение потоков в ядре или виртуализация функций в коде.
Vitaly Muzichenko:
Согласен, можно выпилить ещё 3 строки, и сократить код, но цель была не выложить код к использованию, он по сути даже не мой, а сократить, и таких функций можно поставить пять в один экран, а не одну. После этого программы читаются легче, и не нужно 150 раз скролить. И вес файла уменьшается.
краткость сестра таланта, я думаю так лучше звучит.
Перечитывать отправлять не буду, процитирую: "Не писать функции которые всегда постоянны и никогда не изменяются в таком стиле"
Зачем ковырять глазами функцию, которая пишется один раз при выходе платформы, и никогда не будет меняться в будущем? Вы часто меняете/редактируете код в функциях получения размера лота, количество ордеров и типичных? Тогда зачем её растягивать на 3 экрана 32" монитора?
P.S. Код приложен выковырянный с кодобазы.
Встречный вопрос )) У меня такие функции лежат в файле MyFunc.mqh, не вижу ни малейшего смысла его сжимать. Зачем, сэкономить 10-20 Кб на диске? И если честно, мне от такого кодестайла становится плохо ))
Встречный вопрос )) У меня такие функции лежат в файле MyFunc.mqh, не вижу ни малейшего смысла его сжимать. Зачем, сэкономить 10-20 Кб на диске? И если честно, мне от такого кодестайла становится плохо ))
так же пользуюсь подключаемыми файлами, это удобно. особенно когда пишешь под заказ, много функций одинаковых и писать одно и тоже несколько глупо, подключил файл и функция в советнике. по мне так код должен быть понятным, коротким, быстрым в работе, работать при любых условиях без ошибок.
Встречный вопрос )) У меня такие функции лежат в файле MyFunc.mqh, не вижу ни малейшего смысла его сжимать. Зачем, сэкономить 10-20 Кб на диске? И если честно, мне от такого кодестайла становится плохо ))
Человек же написал, что у него принцип "всё своё ношу с собой", весь код советника запихнут в один файл. Соответственно в каждый советник он копипастит все эти функции. Вот и считай: 1000 советников x 10 кб = 10 Мб - уже есть повод задуматься об экономии ))
Встречный вопрос )) У меня такие функции лежат в файле MyFunc.mqh, не вижу ни малейшего смысла его сжимать. Зачем, сэкономить 10-20 Кб на диске? И если честно, мне от такого кодестайла становится плохо ))
Мне тоже, но как-то давно пришёл к такому выводу, что код должен быть компактный в тех местах, где в него никогда не смотрят, он никогда не правится, и правится не будет.
Разбрасывать пользовательский код по инклудам, это создать ещё одну дополнительную головную боль, чтоб перетащить файл в другой терминал, или им поделиться, нужно таскать не один файл, а несколько. Можно конечно перенести во все терминалы инклудники, но если в одном что подправил или добавил, тогда нужно во всех сделать замену на новый.
Советники и индикаторы настолько малы, что не имеет смысла что-то куда отдалять от тела программы. Вернее они не малы, а однофайловые, это-же не сайт в 10 000 страниц, где без класса и инклудов не обойтись. Тем более, сейчас есть структуры, и их вполне достаточно, чтоб писать компактные на 100% работоспособные коды.
Кстати, меня очень нервирует, когда вложенность более двух уровней. Стараюсь так никогда не писать, раскидывая код по функциям.
И даже когда два уровня вложенности - обязательно после каждой закрывающей скобки - пишу комментарии, какой блок она зарывает (скажем, дублирую заголовок цикла).
Что касается стиля, то вот мой код выбора исторической позиции для МТ5 (по указанному магику, символу, с указанным диапазоном дат):
При этом сам класс истории - это наследник абстрактного интерфейса CTradeHistoryI:
Выбрав необходимую историю - можно пересчитать ее компоненты (позици для МТ5 или ордера для МТ4), и получить интерфейс на любую компоненту в виде абстрактного интерфейса:
Для МТ4 - есть соответствующие классы истории, также наследующиеся от этих интерфейсов - таким образом, заодно обеспечивается и кропссплатформенность - советнику совершенно не надо выяснять, где он работает, вся работа с историей ведется через абстрактные интерфейсы.
Выглядит вкусно, можно еще посмотреть TRACE_*** и ASSERT?
чтоб перетащить файл в другой терминал, или им поделиться, нужно таскать не один файл, а несколько. Можно конечно перенести во все терминалы инклудники, но если в одном что подправил или добавил, тогда нужно во всех сделать замену на новый
Рекомендую использовать символические ссылки или junction-связи для папки MQL. Все терминалы будут смотреть в одну папку.
И потом ковыряйся глазами, к чему относятся эти 4 скобки внизу.
Кстати, меня очень нервирует, когда вложенность более двух уровней. Стараюсь так никогда не писать, раскидывая код по функциям.
И даже когда два уровня вложенности - обязательно после каждой закрывающей скобки - пишу комментарии, какой блок она зарывает (скажем, дублирую заголовок цикла).
Что касается стиля, то вот мой код выбора исторической позиции для МТ5 (по указанному магику, символу, с указанным диапазоном дат):
При этом сам класс истории - это наследник абстрактного интерфейса CTradeHistoryI:
Выбрав необходимую историю - можно пересчитать ее компоненты (позици для МТ5 или ордера для МТ4), и получить интерфейс на любую компоненту в виде абстрактного интерфейса:
Для МТ4 - есть соответствующие классы истории, также наследующиеся от этих интерфейсов - таким образом, заодно обеспечивается и кропссплатформенность - советнику совершенно не надо выяснять, где он работает, вся работа с историей ведется через абстрактные интерфейсы.
Не писать функции которые всегда постоянны и никогда не изменяются в таком стиле
Пишите их сжато, всё-равно в них никогда никто не смотрит, а строк занимает в два раза меньше
Раз эти функции не меняются, то зачем вы там кучу ненужных фигурных скобок понаставили? Уберите их, и всё само сожмётся. А то ваш пример выглядит нелепо: сами же размазали код, а потом выдумываете костыли, чтобы его сократить.
Согласен, можно выпилить ещё 3 строки, и сократить код, но цель была не выложить код к использованию, он по сути даже не мой, а сократить, и таких функций можно поставить пять в один экран, а не одну. После этого программы читаются легче, и не нужно 150 раз скролить. И вес файла уменьшается.
хорошая работа, мне нравиться, но мне не нравиться ООП и стараюсь обходиться без него. как и не нравятся процессоры, с разделением потоков (пример 4 ядра и 8 потоков). должно быть понятно что разделение и любая виртуализация это потеря производительности и потеря машинного времени на ее осуществление, будь то разделение потоков в ядре или виртуализация функций в коде.
Согласен, можно выпилить ещё 3 строки, и сократить код, но цель была не выложить код к использованию, он по сути даже не мой, а сократить, и таких функций можно поставить пять в один экран, а не одну. После этого программы читаются легче, и не нужно 150 раз скролить. И вес файла уменьшается.
с уважением.
Рабочий экран 27"
Перечитывать отправлять не буду, процитирую: "Не писать функции которые всегда постоянны и никогда не изменяются в таком стиле"
Зачем ковырять глазами функцию, которая пишется один раз при выходе платформы, и никогда не будет меняться в будущем? Вы часто меняете/редактируете код в функциях получения размера лота, количество ордеров и типичных? Тогда зачем её растягивать на 3 экрана 32" монитора?
P.S. Код приложен выковырянный с кодобазы.
Встречный вопрос )) У меня такие функции лежат в файле MyFunc.mqh, не вижу ни малейшего смысла его сжимать. Зачем, сэкономить 10-20 Кб на диске? И если честно, мне от такого кодестайла становится плохо ))
Встречный вопрос )) У меня такие функции лежат в файле MyFunc.mqh, не вижу ни малейшего смысла его сжимать. Зачем, сэкономить 10-20 Кб на диске? И если честно, мне от такого кодестайла становится плохо ))
по мне так код должен быть понятным, коротким, быстрым в работе, работать при любых условиях без ошибок.
с уважением.
Встречный вопрос )) У меня такие функции лежат в файле MyFunc.mqh, не вижу ни малейшего смысла его сжимать. Зачем, сэкономить 10-20 Кб на диске? И если честно, мне от такого кодестайла становится плохо ))
Вот и считай: 1000 советников x 10 кб = 10 Мб - уже есть повод задуматься об экономии ))
Встречный вопрос )) У меня такие функции лежат в файле MyFunc.mqh, не вижу ни малейшего смысла его сжимать. Зачем, сэкономить 10-20 Кб на диске? И если честно, мне от такого кодестайла становится плохо ))
Мне тоже, но как-то давно пришёл к такому выводу, что код должен быть компактный в тех местах, где в него никогда не смотрят, он никогда не правится, и правится не будет.
Разбрасывать пользовательский код по инклудам, это создать ещё одну дополнительную головную боль, чтоб перетащить файл в другой терминал, или им поделиться, нужно таскать не один файл, а несколько. Можно конечно перенести во все терминалы инклудники, но если в одном что подправил или добавил, тогда нужно во всех сделать замену на новый.
Советники и индикаторы настолько малы, что не имеет смысла что-то куда отдалять от тела программы. Вернее они не малы, а однофайловые, это-же не сайт в 10 000 страниц, где без класса и инклудов не обойтись. Тем более, сейчас есть структуры, и их вполне достаточно, чтоб писать компактные на 100% работоспособные коды.
Кстати, меня очень нервирует, когда вложенность более двух уровней. Стараюсь так никогда не писать, раскидывая код по функциям.
И даже когда два уровня вложенности - обязательно после каждой закрывающей скобки - пишу комментарии, какой блок она зарывает (скажем, дублирую заголовок цикла).
Что касается стиля, то вот мой код выбора исторической позиции для МТ5 (по указанному магику, символу, с указанным диапазоном дат):
При этом сам класс истории - это наследник абстрактного интерфейса CTradeHistoryI:
Выбрав необходимую историю - можно пересчитать ее компоненты (позици для МТ5 или ордера для МТ4), и получить интерфейс на любую компоненту в виде абстрактного интерфейса:
Для МТ4 - есть соответствующие классы истории, также наследующиеся от этих интерфейсов - таким образом, заодно обеспечивается и кропссплатформенность - советнику совершенно не надо выяснять, где он работает, вся работа с историей ведется через абстрактные интерфейсы.
Выглядит вкусно, можно еще посмотреть TRACE_*** и ASSERT?
чтоб перетащить файл в другой терминал, или им поделиться, нужно таскать не один файл, а несколько. Можно конечно перенести во все терминалы инклудники, но если в одном что подправил или добавил, тогда нужно во всех сделать замену на новый