Und dann müssen Sie nachschlagen, worauf sich die vier Klammern am unteren Rand beziehen.
Übrigens macht es mich sehr nervös, wenn die Verschachtelung mehr als zwei Ebenen umfasst. Ich versuche, es nie so zu schreiben und den Code über Funktionen zu verteilen.
Und selbst wenn es zwei Verschachtelungsebenen gibt - achten Sie darauf, nach jeder schließenden Klammer einen Kommentar zu schreiben, der angibt, welcher Block verschüttet wird (z. B. ein doppelter Schleifenkopf).
Wie für Stil, hier ist mein Code für die Auswahleiner Geschichte Position für MT5 (von einem bestimmten Magier, Symbol, mit einem bestimmten Datum Bereich):
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());
};
Die History-Klasse selbst ist ein Abkömmling der abstrakten Schnittstelle 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;
};
Durch Auswahl der gewünschten Historie können Sie deren Komponenten (Positionen für MT5 oder Aufträge für MT4) neu berechnen und eine Schnittstelle zu jeder Komponente als abstrakte Schnittstelle erhalten:
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;
};
Für MT4 gibt es entsprechende History-Klassen, die ebenfalls von diesen Interfaces geerbt werden - damit ist gleichzeitig die Cross-Plattformalität gegeben - ein EA muss nicht herausfinden, wo er arbeitet, die gesamte Arbeit mit der History wird über die abstrakten Interfaces erledigt.
Schreiben Sie keine Funktionen, die immer konstant sind und sich nie ändern, in diesem Stil
Schreiben Sie sie kurz und bündig, niemand schaut sie sich an, und sie brauchen nur halb so viele Zeilen.
Da sich diese Funktionen nie ändern, warum setzen Sie dort einen Haufen unnötiger geschweifter Klammern? Entfernen Sie sie, und alles wird von selbst schrumpfen. Denn Ihr Beispiel wirkt absurd: Sie selbst haben den Code verwischt und erfinden dann Krücken, um ihn zu reduzieren.
Alexey Navoykov: Da sich diese Funktionen nicht ändern, warum haben Sie dort einen Haufen unnötiger geschweifter Klammern gesetzt? Entfernen Sie sie, und alles wird komprimiert. Denn Ihr Beispiel wirkt absurd: Sie selbst haben den Code verwischt und erfinden dann Krücken, um ihn zu reduzieren.
Ich stimme zu, man kann 3 weitere Zeilen herausschneiden und den Code kürzen, aber der Zweck war nicht, den Code zu verwenden, er ist nicht einmal meiner, sondern ihn zu kürzen, und man kann fünf solcher Funktionen in einem Bildschirm unterbringen, nicht eine. Danach sind die Programme leichter zu lesen und man muss nicht 150 Mal blättern. Und das Gewicht der Datei sinkt.
Nette Arbeit, gefällt mir, aber ich mag OOP nicht und versuche, darauf zu verzichten. Ich mag keine Prozessoren mit Threadsplitting (z.B. 4 Kerne und 8 Threads). Es muss klar sein, dass Splitting und jede Virtualisierung einen Leistungsverlust und einen Verlust an Maschinenzeit für die Implementierung bedeutet, sei es Threadsplitting im Kernel oder Virtualisierung von Funktionen im Code.
Vitaly Muzichenko:
Ich stimme zu, Sie können 3 weitere Zeilen herausschneiden und den Code kürzen, aber der Zweck war nicht, den Code zu verwenden, es ist in der Tat nicht einmal meine, sondern zu verkürzen, und solche Funktionen können fünf in einem Bildschirm, nicht eine gesetzt werden. Danach sind die Programme leichter zu lesen und man muss nicht 150 Mal blättern. Und das Gewicht der Datei wird reduziert.
Kürze ist die Schwester des Talents, ich finde, das klingt besser.
Ich werde ihn nicht noch einmal lesen, sondern nur zitieren:"Schreiben Sie keine Funktionen, die immer gleich bleiben und sich nie in diesem Stil ändern".
Warum sollte man sich über eine Funktion aufregen, die einmal geschrieben wird, wenn die Plattform freigegeben wird, und die sich in der Zukunft nie ändern wird? Ändern Sie häufig den Code in den Funktionen, um die Losgröße, die Anzahl der Aufträge und die typischen Werte zu erhalten? Warum sollte man sie dann auf 3 Bildschirme eines 32-Zoll-Monitors verteilen?
P.S. Der beigefügte Code ist eine Fälschung von kodobase.
Gegenfrage ))) Ich habe solche Funktionen in der Datei MyFunc.mqh, ich sehe nicht den geringsten Sinn darin, sie zu komprimieren. Warum, um 10-20 KB auf der Festplatte zu sparen? Und offen gesagt, macht mich ein solcher Codestream krank ))
Gegenfrage ))) Ich habe solche Funktionen in der Datei MyFunc.mqh, ich sehe nicht den geringsten Sinn darin, sie zu komprimieren. Warum, um 10-20 KB auf der Festplatte zu sparen? Um ehrlich zu sein, dieser Codestream macht mich krank )).
Ich benutze auch Include-Dateien, das ist praktisch, vor allem wenn man ein eigenes Skript schreibt, es gibt viele identische Funktionen und es ist dumm, ein und dasselbe zu schreiben, man muss nur die Datei einbinden und schon ist die Funktion im EA. Was mich betrifft, so sollte der Code klar, kurz und schnell sein und unter allen Bedingungen ohne Fehler funktionieren.
Gegenfrage ))) Ich habe solche Funktionen in der Datei MyFunc.mqh, ich sehe nicht den geringsten Sinn darin, sie zu komprimieren. Warum, um 10-20 KB auf der Festplatte zu sparen? Und ehrlich gesagt, ein solcher Codestream macht mich krank ))
Der Programmierer hat sich das Prinzip "Ich trage alles selbst" auf die Fahne geschrieben; der gesamte Code des Expert Advisors ist in eine einzige Datei gezwängt. Dementsprechend kopiert er alle diese Funktionen in jeden EA. Also, rechnen Sie: 1000 EAs x 10 Kb = 10 Mb - da müssen Sie schon über Einsparungen nachdenken ))
Gegenfrage ))) Ich habe solche Funktionen in der Datei MyFunc.mqh, ich sehe nicht den geringsten Sinn darin, sie zu komprimieren. Warum, um 10-20 KB auf der Festplatte zu sparen? Und offen gesagt, macht mich ein solcher Codestream krank ))
Ich auch, aber ich bin schon vor langer Zeit zu dem Schluss gekommen, dass der Kodex an Orten kompakt sein muss, wo man ihn nie ansieht, wo er nie korrigiert wird und nie korrigiert werden wird.
Das Verteilen von Benutzercode mit all diesen Steckplätzen bereitet zusätzliche Kopfschmerzen, da Sie die Dateien auf verschiedene Terminals ziehen oder gemeinsam nutzen müssen. Natürlich können Sie die Includniks auf alle Terminals übertragen, aber wenn Sie in einem Terminal etwas ändern oder hinzufügen, müssen alle durch ein neues Terminal ersetzt werden.
Die Expert Advisors und Indikatoren sind so klein, dass es keinen Sinn macht, sie vom Hauptteil des Programms zu trennen. Um genau zu sein, sie sind nicht klein, sie sind eine einzige Datei, es ist nicht wie bei einer Website mit 10 000 Seiten, wo man nicht ohne Klassen und Einschübe auskommt. Außerdem gibt es jetzt Strukturen, und die reichen aus, um kompakten, 100 % funktionsfähigen Code zu schreiben.
Übrigens macht es mich sehr nervös, wenn die Verschachtelung mehr als zwei Ebenen umfasst. Ich versuche, es nie so zu schreiben und den Code über Funktionen zu verteilen.
Und selbst wenn es zwei Verschachtelungsebenen gibt - achten Sie darauf, nach jeder schließenden Klammer einen Kommentar zu schreiben, der angibt, welchen Block sie verdeckt (z. B. einen doppelten Schleifenkopf).
Wie für Stil, hier ist mein Code für die Auswahleiner Geschichte Position für MT5 (von bestimmten Magier, Symbol, mit bestimmten Datum Bereich):
Die History-Klasse selbst ist ein Abkömmling der abstrakten Schnittstelle CTradeHistoryI:
Durch Auswahl der gewünschten Historie können Sie deren Komponenten (Positionen für MT5 oder Aufträge für MT4) neu berechnen und eine Schnittstelle zu jeder Komponente als abstrakte Schnittstelle erhalten:
Für MT4 gibt es entsprechende History-Klassen, die ebenfalls von diesen Interfaces erben - damit ist gleichzeitig die Cross-Plattformalität gegeben - der Expert Advisor muss nicht herausfinden, wo er arbeitet, die gesamte Arbeit mit der History wird über abstrakte Interfaces erledigt.
Sieht gut aus, können wir uns auch TRACE_*** und ASSERT ansehen?
Um eine Datei auf ein anderes Terminal zu ziehen und dort abzulegen oder sie freizugeben, müssen Sie nicht nur eine Datei ziehen, sondern mehrere. Natürlich können Sie die Inludes auf alle Terminals übertragen, aber wenn Sie in einem Terminal etwas ändern oder hinzufügen, müssen Sie es in allen Terminals durch ein neues ersetzen.
Ich empfehle die Verwendung von symbolischen Links oder Junction Links für den MQL-Ordner. Alle Terminals werden in einem Ordner gesucht.
Wenn Sie kein Benutzerkonto haben, registrieren Sie sich
Erlauben Sie die Verwendung von Cookies, um sich auf der Website MQL5.com anzumelden.
Bitte aktivieren Sie die notwendige Einstellung in Ihrem Browser, da Sie sich sonst nicht einloggen können.
Sie sind angemeldet. Die Zwei-Faktor-Authentifizierung wurde deaktiviert. Richten Sie sie erneut ein und scannen Sie einen neuen QR-Code oder fahren Sie mit deaktivierter Zwei-Faktor-Authentifizierung fort.
Und dann müssen Sie nachschlagen, worauf sich die vier Klammern am unteren Rand beziehen.
Übrigens macht es mich sehr nervös, wenn die Verschachtelung mehr als zwei Ebenen umfasst. Ich versuche, es nie so zu schreiben und den Code über Funktionen zu verteilen.
Und selbst wenn es zwei Verschachtelungsebenen gibt - achten Sie darauf, nach jeder schließenden Klammer einen Kommentar zu schreiben, der angibt, welcher Block verschüttet wird (z. B. ein doppelter Schleifenkopf).
Wie für Stil, hier ist mein Code für die Auswahleiner Geschichte Position für MT5 (von einem bestimmten Magier, Symbol, mit einem bestimmten Datum Bereich):
Die History-Klasse selbst ist ein Abkömmling der abstrakten Schnittstelle CTradeHistoryI:
Durch Auswahl der gewünschten Historie können Sie deren Komponenten (Positionen für MT5 oder Aufträge für MT4) neu berechnen und eine Schnittstelle zu jeder Komponente als abstrakte Schnittstelle erhalten:
Für MT4 gibt es entsprechende History-Klassen, die ebenfalls von diesen Interfaces geerbt werden - damit ist gleichzeitig die Cross-Plattformalität gegeben - ein EA muss nicht herausfinden, wo er arbeitet, die gesamte Arbeit mit der History wird über die abstrakten Interfaces erledigt.
Schreiben Sie keine Funktionen, die immer konstant sind und sich nie ändern, in diesem Stil
Schreiben Sie sie kurz und bündig, niemand schaut sie sich an, und sie brauchen nur halb so viele Zeilen.
Da sich diese Funktionen nicht ändern, warum haben Sie dort einen Haufen unnötiger geschweifter Klammern gesetzt? Entfernen Sie sie, und alles wird komprimiert. Denn Ihr Beispiel wirkt absurd: Sie selbst haben den Code verwischt und erfinden dann Krücken, um ihn zu reduzieren.
Ich stimme zu, man kann 3 weitere Zeilen herausschneiden und den Code kürzen, aber der Zweck war nicht, den Code zu verwenden, er ist nicht einmal meiner, sondern ihn zu kürzen, und man kann fünf solcher Funktionen in einem Bildschirm unterbringen, nicht eine. Danach sind die Programme leichter zu lesen und man muss nicht 150 Mal blättern. Und das Gewicht der Datei sinkt.
Nette Arbeit, gefällt mir, aber ich mag OOP nicht und versuche, darauf zu verzichten. Ich mag keine Prozessoren mit Threadsplitting (z.B. 4 Kerne und 8 Threads). Es muss klar sein, dass Splitting und jede Virtualisierung einen Leistungsverlust und einen Verlust an Maschinenzeit für die Implementierung bedeutet, sei es Threadsplitting im Kernel oder Virtualisierung von Funktionen im Code.
Ich stimme zu, Sie können 3 weitere Zeilen herausschneiden und den Code kürzen, aber der Zweck war nicht, den Code zu verwenden, es ist in der Tat nicht einmal meine, sondern zu verkürzen, und solche Funktionen können fünf in einem Bildschirm, nicht eine gesetzt werden. Danach sind die Programme leichter zu lesen und man muss nicht 150 Mal blättern. Und das Gewicht der Datei wird reduziert.
Mit freundlichen Grüßen.
27"-Arbeitsbildschirm
Ich werde ihn nicht noch einmal lesen, sondern nur zitieren:"Schreiben Sie keine Funktionen, die immer gleich bleiben und sich nie in diesem Stil ändern".
Warum sollte man sich über eine Funktion aufregen, die einmal geschrieben wird, wenn die Plattform freigegeben wird, und die sich in der Zukunft nie ändern wird? Ändern Sie häufig den Code in den Funktionen, um die Losgröße, die Anzahl der Aufträge und die typischen Werte zu erhalten? Warum sollte man sie dann auf 3 Bildschirme eines 32-Zoll-Monitors verteilen?
P.S. Der beigefügte Code ist eine Fälschung von kodobase.
Gegenfrage ))) Ich habe solche Funktionen in der Datei MyFunc.mqh, ich sehe nicht den geringsten Sinn darin, sie zu komprimieren. Warum, um 10-20 KB auf der Festplatte zu sparen? Und offen gesagt, macht mich ein solcher Codestream krank ))
Gegenfrage ))) Ich habe solche Funktionen in der Datei MyFunc.mqh, ich sehe nicht den geringsten Sinn darin, sie zu komprimieren. Warum, um 10-20 KB auf der Festplatte zu sparen? Um ehrlich zu sein, dieser Codestream macht mich krank )).
Was mich betrifft, so sollte der Code klar, kurz und schnell sein und unter allen Bedingungen ohne Fehler funktionieren.
Mit freundlichen Grüßen.
Gegenfrage ))) Ich habe solche Funktionen in der Datei MyFunc.mqh, ich sehe nicht den geringsten Sinn darin, sie zu komprimieren. Warum, um 10-20 KB auf der Festplatte zu sparen? Und ehrlich gesagt, ein solcher Codestream macht mich krank ))
Also, rechnen Sie: 1000 EAs x 10 Kb = 10 Mb - da müssen Sie schon über Einsparungen nachdenken ))
Gegenfrage ))) Ich habe solche Funktionen in der Datei MyFunc.mqh, ich sehe nicht den geringsten Sinn darin, sie zu komprimieren. Warum, um 10-20 KB auf der Festplatte zu sparen? Und offen gesagt, macht mich ein solcher Codestream krank ))
Ich auch, aber ich bin schon vor langer Zeit zu dem Schluss gekommen, dass der Kodex an Orten kompakt sein muss, wo man ihn nie ansieht, wo er nie korrigiert wird und nie korrigiert werden wird.
Das Verteilen von Benutzercode mit all diesen Steckplätzen bereitet zusätzliche Kopfschmerzen, da Sie die Dateien auf verschiedene Terminals ziehen oder gemeinsam nutzen müssen. Natürlich können Sie die Includniks auf alle Terminals übertragen, aber wenn Sie in einem Terminal etwas ändern oder hinzufügen, müssen alle durch ein neues Terminal ersetzt werden.
Die Expert Advisors und Indikatoren sind so klein, dass es keinen Sinn macht, sie vom Hauptteil des Programms zu trennen. Um genau zu sein, sie sind nicht klein, sie sind eine einzige Datei, es ist nicht wie bei einer Website mit 10 000 Seiten, wo man nicht ohne Klassen und Einschübe auskommt. Außerdem gibt es jetzt Strukturen, und die reichen aus, um kompakten, 100 % funktionsfähigen Code zu schreiben.
Übrigens macht es mich sehr nervös, wenn die Verschachtelung mehr als zwei Ebenen umfasst. Ich versuche, es nie so zu schreiben und den Code über Funktionen zu verteilen.
Und selbst wenn es zwei Verschachtelungsebenen gibt - achten Sie darauf, nach jeder schließenden Klammer einen Kommentar zu schreiben, der angibt, welchen Block sie verdeckt (z. B. einen doppelten Schleifenkopf).
Wie für Stil, hier ist mein Code für die Auswahleiner Geschichte Position für MT5 (von bestimmten Magier, Symbol, mit bestimmten Datum Bereich):
Die History-Klasse selbst ist ein Abkömmling der abstrakten Schnittstelle CTradeHistoryI:
Durch Auswahl der gewünschten Historie können Sie deren Komponenten (Positionen für MT5 oder Aufträge für MT4) neu berechnen und eine Schnittstelle zu jeder Komponente als abstrakte Schnittstelle erhalten:
Für MT4 gibt es entsprechende History-Klassen, die ebenfalls von diesen Interfaces erben - damit ist gleichzeitig die Cross-Plattformalität gegeben - der Expert Advisor muss nicht herausfinden, wo er arbeitet, die gesamte Arbeit mit der History wird über abstrakte Interfaces erledigt.
Sieht gut aus, können wir uns auch TRACE_*** und ASSERT ansehen?
Um eine Datei auf ein anderes Terminal zu ziehen und dort abzulegen oder sie freizugeben, müssen Sie nicht nur eine Datei ziehen, sondern mehrere. Natürlich können Sie die Inludes auf alle Terminals übertragen, aber wenn Sie in einem Terminal etwas ändern oder hinzufügen, müssen Sie es in allen Terminals durch ein neues ersetzen.