English Русский 中文 Español 日本語 Português 한국어 Français Italiano Türkçe
Automatenbasierte Programmierung als neue Herangehensweise an die Erstellung automatisierter Handelssysteme

Automatenbasierte Programmierung als neue Herangehensweise an die Erstellung automatisierter Handelssysteme

MetaTrader 5Handel | 29 April 2016, 16:09
957 0
MT5
[Gelöscht]

ἓν οἶδα ὅτι οὐδὲν οἶδα (ο φιλόσοφος Σωκράτης)

Ich weiß, dass ich nichts weiß (der Philosoph Sokrates)


Einleitung

Zum Einstieg möchte ich erwähnen, dass dieses Thema für Händler, die EAs mit der MetaQuotes Language 4/5 (MQL4/5) entwickeln, völlig neu ist. Davon konnte ich mich selbst überzeugen, als ich versuchte, eine entsprechende Suche auf der Webseite von MetaQuotes durchzuführen. Es gibt nichts zu diesem Thema.

Jeder Händler erstellt seinen eigenen Expert Advisor, der eine ernsthafte Herangehensweise an alle möglichen Probleme erfordert, die mit der Programmierung und einer sehr komplizierten Programmlogik verbunden sind. Letztendlich wird vom Programm erwartet, dass es SELBSTSTÄNDIG wie ein Uhrwerk in jeder Standardsituation und Situation höherer Gewalt läuft.

Aber wie kann man alles berücksichtigen? Das ist extrem schwierig, weshalb automatische Kontrollsysteme eine ordentliche Programmierung aller Kontrollsysteme erfordertn Dies lässt sich am besten mithilfe der einzigen geeigneten Programmiertechnologie, der automatenbasierten Programmierung, erzielen. In den letzten Jahren wurde der Entwicklung von Programmiertechnologien für eingebettete und Echtzeitsysteme, die hohe Anforderungen an die Qualität der Software stellen, eine hohe Aufmerksamkeit gewidmet.

1991 entwickelte der russische Autor A.A. Schalyto (Dozent, Professor, Doktor der Naturwissenschaften in Ingenieurwissenschaften, Vorsitzender des Fachbereichs "Programmiertechnologien" an der SPbSU ITMO) eine Programmiertechnologie, die er als "automatenbasierte Programmierung" bezeichnete. Ich glaube, für die Leser könnte es interessant sein, zu sehen, wie einfach die automatenbasierte Programmierung oder SWITCH-Technologie sein kann. Sie ermöglicht die Entwicklung von MTS mithilfe der MetaQuotes Language auf eine so bequeme Art, dass es gar nicht besser sein könnte. Und sie passt perfekt in das System der komplexen Entscheidungsfindung.


1. Herantasten an das Problem

Ein lang gehegter Traum von allen Aufgabenstellern und Softwareentwicklern muss es sein, eine planmäßige Lösung für die Aufgabe (den Algorithmus) und eine Umsetzung dieses Algorithmus zu haben, der dieser vollständig entspricht. Doch das scheint für die Aufgabensteller und Entwickler nicht so zu klappen. Algorithmen lassen oft aus, was für Entwickler wichtig für die Umsetzung ist, während der Programmtext an sich wenig Ähnlichkeit mit dem Algorithmus hat.

Somit gibt es zwei Algorithmen: einen auf dem Papier (fürs Aufzeichnen und Dokumentieren von Konzeptlösungen), der für gewöhnlich ein bestimmtes Konzeptergebnis anstatt der Methoden zum Erhalten eines bestimmten Ergebnisses darstellt, und einen zweiten im Kopf des Entwicklers (der allerdings auch in Textform gespeichert wird).

Auf die finale Version des Programmtexts folgen oft Versuche, die Dokumentation zu verändern, wobei erneut vieles nicht berücksichtigt wird. In diesem Fall unterscheidet sich die Programmlogik mit hoher Wahrscheinlichkeit von der Logik des Algorithmus und demonstriert damit mangelnde Übereinstimmung. Ich sage absichtlich "mit hoher Wahrscheinlichkeit", da niemand je den Programmtext von jemandem prüfen wird.

Wenn das Programm groß ist, ist es unmöglich, nur anhand des Textes zu prüfen, ob es dem Algorithmus entspricht. Die Genauigkeit der Umsetzung lässt sich mit einer Prozedur namens "Testing" prüfen. Im Wesentlichen wird dabei geprüft, wie der Entwickler den Algorithmus (den auf dem Papier) verstanden, ihn in einen weiteren Algorithmus in seinem Kopf übertragen und das Ganze als Programm umgesetzt hat. Letztendlich ist der Entwickler der Einzige, der über wertvolle Informationen über die Logik verfügt, und alles, was vor der Umsetzung erdacht wurde, wird vollkommen irrelevant.

Das Problem ist nicht einmal, dass der Entwickler krank werden (oder kündigen) kann. Das Problem ist, dass die zugrunde liegende Programmlogik mit jedem Entwickler anders wäre, je nach seiner Intelligenz und Kenntnis einer Programmiersprache. In allen Fällen führt der Entwickler zahlreiche Zwischenvariablen ein und nutzt sie nach eigenem Ermessen. Und wenn das Programm groß und logisch komplex ist, liegt es an einem qualifizierteren Spezialisten, die Fehler zu finden (und ich meine hier keine Fehler des Betriebssystems oder die falsche Verwendung von Funktionen der Sprache, sondern eher eine nicht ordnungsgemäße Umsetzung hinsichtlich der Logik) und das Problem im Programmtext selbst zu beheben.

Die meisten Entwickler sind, gelinde gesagt, nicht gerade darauf erpicht, Algorithmen vor dem Programmieren aufzuschreiben (oder sie auch nur auf dem Papier zu skizzieren), was vermutlich daran liegt, dass sie sich im weiteren Verlauf noch etwas ausdenken müssen. Warum sollte man auch Zeit damit verschwenden, Rechtecke, Diamanten und Pfeile zu zeichnen, wo es doch besser ist, sofort mit dem Programmieren anzufangen und dann einen mehr oder weniger ähnlichen oder sehr allgemeinen Algorithmus in der Dokumentation zu entwerfen?

Jeder hat sich daran gewöhnt. Entwickler tun es, weil es einfacher ist, während Aufgabensteller nicht immer über die nötigen Programmierkenntnisse verfügen, und selbst wenn sie es tun, können sie nicht rechtzeitig Einfluss darauf nehmen, was Entwickler sich ausdenken. Bequeme Programmierumgebungen tragen ebenfalls zur Validität dieses Programmierablaufs bei. Moderne Tools zum Debuggen und zum Überwachen von Werten von Variablen lassen uns hoffen, etwaige Fehler in der Logik finden zu können.

Während die Zeit davonläuft und das Projekt sich seiner Deadline nähert, sitzt der Entwickler da und skizziert auf einem Papiertuch Lösungen für ein bestimmtes logisches Problem, die auch immer noch implementiert werden müssen, von Fehlern, die beim Testing übersehen wurden, ganz zu schweigen, da das Testing so ziemlich dem gleichen (chaotischen) Schema folgt... So sieht die Situation aktuell aus. Gibt es eine Lösung oder kann sie zumindest verbessert werden? Man erhält den Eindruck, dass etwas Wichtiges beim Übergang von einem standardmäßig dargestellten Algorithmus zum Programmcode verlorengeht.


2. Logischer Teil des Programms

Der Verfasser von "automatenbasierte Programmierung" hat das folgende Konzept eines idealen logischen Teils eines Programms vorgeschlagen. Die gesamte Logik des Programms basiert auf dem Switch. Vereinfacht gesagt, kann jeder beliebige Steueralgorithmus (Automat) umgesetzt werden, wie unten dargestellt (denken Sie noch nicht zu sehr über die Bedeutung der Kommentare nach, sehen Sie sich einfach nur die Struktur an).

switch(int STATUS ) // Мulti-valued global state variable of the automaton.
{
  case 0:  // start

  // Checking arc and loop conditions (in order of priority),
  // transition (change of the value of the variable STATUS)
  // and execution of arc and loop actions (output function execution);
  // logging transitions and actions if the condition is met. 0

  // Calling nested automata.
  // Execution of output functions in the state.
  break ;
  
  case 1:
  // Checking arc and loop conditions (in order of priority),
  // transition (change of the value of the variable STATUS)
  // and execution of arc and loop actions (output function execution);
  // logging transitions and actions if the condition is met. 

  // Calling nested automata.
  // Execution of output functions in the state.
  break ;
  
*********
*********
*********

 case N-1:
  // Checking arc and loop conditions (in order of priority),
  // transition (change of the value of the variable STATUS)
  // and execution of arc and loop actions (output function execution);
  // logging transitions and actions if the condition is met. 

  // Calling nested automata.
  // Execution of output functions in the state.
  break ;

 case N:
  // Checking arc and loop conditions (in order of priority),
  // transition (change of the value of the variable STATUS)
  // and execution of arc and loop actions (output function execution);
  // logging transitions and actions if the condition is met.

  // Calling nested automata.
  // Execution of output functions in the state.
  break ;
}


3. Automatenbasierte Programmierung laut A.A. Schalyto

Unabhängig von den Entwicklungstechniken hat jedes Programm Zustände, die durch die Gesamtheit seiner Datenwerte zu einem bestimmten Zeitpunkt bestimmt werden. In einer großen Anwendung kann es hunderte und sogar tausende Variablen und mehrere Steuerungsrichtungen geben. Ein vollständiger Satz dieser Variablen beschreibt den Zustand der Anwendung zu jedem bestimmten Zeitpunkt.

Der Programmzustand kann auf einfachere Art als Sammlung der Werte aller Kontrollvariablen behandelt werden, die an allen Übergangsbedingungen beteiligt sind. Eine Änderung des Wertes einer der Kontrollvariablen bedeutet eine Änderung des Programmzustands. Die Menge der Programmzustände wird durch die höchstmögliche Menge von Kombinationen von Kontrollvariablenwerten bestimmt, die während des Betriebs des Programms entstehen. Nehmen wir an, dass ein Programm nur binäre Kontrollvariablen (Flags) nutzt. Die Menge der Zustände eines Programms, das n binäre Kontrollvariablen enthält, liegt in diesem Fall im Bereich zwischen n und 2n.

Es ist möglich, dass der Entwickler Reaktionen auf alle Kombinationen von Kontrollvariablenwerten vorgesehen hat (2n Kombinationen in unserem Fall). Wahrscheinlicher ist allerdings, dass einige Kombinationen von Kontrollvariablenwerten (bis zu 2n-n) sich als nicht vorgesehen erwiesen haben. Wenn nun eine unerwartete Kombination von Eingabeaktionen entsteht, kann das Programm in einen nicht vorgesehenen Zustand übergehen.

Für einen Händler hat das die gleichen Auswirkungen wie die Untätigkeit eines EAs in den folgenden Fällen:

  • Lücke,
  • Verlust der Einlage,
  • Negativbilanzsituation mit anschließendem Margin Call,
  • kein Festhalten guter Rendite, die anschließend auf Null und weiter ins Negative fällt,
  • inkorrektes Öffnen und Schließen von Longs und Shorts,
  • sonstige offensichtlich nachteilige Situationen.

Solche Zustände werden als "nicht visualisiert" bezeichnet. Die Ursache für die Schwierigkeit, alle möglichen Zustände des Programms, die zu einem Mangel an Zuverlässigkeit führen, aufzuzählen und zu verstehen, wird durch Komplexität verursacht. Komplexe Strukturen sind der Ursprung von nicht visualisierten Zuständen, die die Sicherheit des Systems gefährden. Das Verhalten des Programms in einem nicht vorgesehen Zustand reicht von Störungen beim Speicherschutz bis zur Erweiterung des Programms um neue Funktionen mit diversen Nebeneffekten.

Viele PC-Benutzer und höchstwahrscheinlich alle Softwareentwickler sind oft in Situationen geraten, in denen ein genutztes oder zu entwickelndes Programm in einen nicht vorgesehenen Zustand gerät.

Um die reine Möglichkeit nicht vorgesehener Zustände im Programm zu beseitigen, müssen alle benötigten Zustände bereits in der Konzeptphase explizit festgelegt werden und für ihre Unterscheidung darf nur eine mehrwertige Kontrollvariable verwendet werden. Danach müssen alle möglichen Übergänge zwischen den Zuständen identifiziert und ein Programm entwickelt werden, das nicht "entgleisen" kann.

Drei Komponenten werden benötigt, um das Verhalten des Programms präzise zu entwickeln:

  • Mathematisches Modell, das eine eindeutige Identifizierung von Programmzuständen und möglichen Übergängen zwischen ihnen ermöglicht;
  • Grafische Notation für dieses Modell;
  • Universelle Methode für die Umsetzung der in dieser Notation ausgedrückten Algorithmen.

Für die Nutzung als mathematisches Modell wird ein endlicher Automat auf Basis der Vorstellung des "Zustands" vorgeschlagen. Die automatenbasierte Programmierung unterstützt Phasen der Softwareentwicklung wie Konzeptionierung, Implementierung, Debugging und Dokumentation.

Während der Begriff "Ereignis" in den letzten Jahren immer häufiger in der Programmierung genutzt wurde, basiert die vorgeschlagene Vorgehensweise auf der Vorstellung des "Zustands". Nach dem Hinzufügen des Begriffs "Eingangsaktion", die entweder eine Eingabevariable oder ein Ereignis sein kann, wird der Begriff "Automat ohne Ausgang" eingeführt. Auf letzteren folgt der Begriff "Ausgangsaktion" und die Idee des (deterministischen endlichen) Automaten wird eingeführt. Der auf diesem Konzept basierende Bereich der Programmierung wird deshalb als automatenbasierte Programmierung bezeichnet und der dazugehörige Entwicklungsprozess wird automatenbasiertes Programmdesign genannt.

Eine Besonderheit der beschriebenen Herangehensweise ist, dass bei ihrem Gebrauch Automaten durch Übergangsdiagramme repräsentiert werden. Zur Unterscheidung ihrer Knoten wird der Begriff "Statuszuweisung" eingeführt. Bei der Auswahl einer "mehrwertigen Statuszuweisung" können die Status, deren Menge mit der Menge der Werte übereinstimmt, die die gewählte Variable annehmen kann, mithilfe nur einer Variable unterschieden werden. Dies ermöglicht die Einführung des Begriffs Beobachtbarkeit des Programms in die Programmierung.

Die Programmierung mit der vorgeschlagenen Herangehensweise geschieht mithilfe von "Status" anstelle von "Variablen" (Flags), was zum besseren Verständnis und zu einer genaueren Festlegung der Aufgabe und ihrer Komponenten beiträgt. Das Debugging geschieht in diesem Fall durch die Protokollierung in den Begriffen der Automaten.

Da die oben aufgeführte Herangehensweise nahelegt, mithilfe einer formalen und isomorphen Methode vom Übergangsdiagramm zum Programmcode überzugehen, erscheint es sinnvoller, dies mithilfe von Switch-Strukturen zu bewerkstelligen, wenn höhere Programmiersprachen genutzt werden. Deshalb wurde beschlossen, den Begriff "SWITCH-Technologie" zu nutzen, wenn man vom automatenbasierten Programmierparadigma spricht.


4. Explizite zustandsbasierte Programmierung

Die Anwendung der automatenbasierten Herangehensweise wurde auf ereignisgesteuerte Systeme erweitert, die auch als "reaktiv" bezeichnet werden. Reaktive Systeme interagieren mit der Umgebung mithilfe von Meldungen in einem von der Umgebung festgelegten Tempo (ein EA lässt sich in diese Klasse integrieren).

Die Entwicklung ereignisgesteuerter Systeme mithilfe von Automaten wurde durch den Einsatz der prozesshaften Vorgehensweise ermöglicht, woraus der Name explizite zustandsbasierte Programmierung entstanden ist. Ausgangsaktionen werden bei dieser Methode den Bögen, Schleifen oder Knoten von Übergangsdiagrammen zugewiesen (es werden gemischte Automaten – Moore- und Mealy-Automaten – genutzt). Dies ermöglicht eine kompakte Darstellung der Abfolge von Aktionen, die ihrerseits Reaktionen auf die jeweiligen Eingangsaktionen sind.

Die vorgeschlagene Herangehensweise an die Programmierung dieser Klasse von Systemen besteht aus einer stärkeren Zentralisierung der Logik, da sie aus Ereignis-Handlern entfernt wird, und der Erzeugung eines Systems aus untereinander verbundenen Automaten, die über die Handler aufgerufen werden. Die Interaktion zwischen Automaten in einem solchen System lässt sich durch Verschachteln, Aufrufen und Austauschen der Nummern von Zuständen erreichen.

Das System aus untereinander verbundenen Diagrammen formt einen systemunabhängigen Programmteil, während durch Funktionen von Eingangs- und Ausgangsfunktionen, Handlern usw. ein systemabhängiger Teil geformt wird.

Ein weiteres wichtiges Merkmal dieser Herangehensweise ist, dass Automaten bei ihrer Anwendung dreifach genutzt werden:

  • bei der Spezifikation;
  • bei der Implementierung (sie verbleiben im Programmcode);
  • beim Protokollieren in den Begriffen der Automaten (wie oben festgelegt).

Der letzte Punkt erlaubt es, die Genauigkeit des Betriebs des Automatensystems zu kontrollieren. Die Protokollierung geschieht automatisch auf Basis des entwickelten Programms und kann für weit gefasste Aufgaben mit komplexer Programmlogik verwendet werden. Jedes Protokoll lässt sich in diesem Fall als relevantes Script verstehen.

Protokolle ermöglichen die Überwachung des Betriebs des Programms und illustrieren die Tatsache, dass Automaten keine "Bilder" sind, sondern reale und aktive Entitäten. Die automatenbasierte Herangehensweise wird nicht nur für die Erstellung eines Kontrollsystems empfohlen, sondern auch beim Modellieren von Kontrollobjekten.


5. Grundlegende Konzepte der automatenbasierten Programmierung

Das grundlegende Konzept der automatenbasierten Programmierung ist der ZUSTAND. Die wichtigste Eigenschaft des Systemzustands bei jeder spezifischen Zeit t0 besteht in der "Trennung" der Zukunft (t > t0) von der Vergangenheit (t < t0) in dem Sinne, dass der aktuelle Zustand alle Informationen über die Vergangenheit des Systems enthält, die zur Bestimmung seiner Reaktionen auf alle zu jedem bestimmten Zeitpunkt t0 erzeugten Eingangsaktionen benötigt werden.

Bei der Verwendung des Begriffs ZUSTAND ist keine Kenntnis der historischen Daten erforderlich. Der Zustand kann als spezielle Eigenschaft betrachtet werden, die implizit alle Eingangsaktionen aus der Vergangenheit kombiniert, die die Reaktion der Entität in der Gegenwart beeinflussen. Die Reaktion hängt nun nur von der Eingangsaktion und dem aktuellen Zustand ab.

Das Konzept der "Eingangsaktion" ist ebenfalls eins der zentralen Konzepte bei der automatenbasierten Programmierung. Eine Eingangsaktion ist in den meisten Fällen ein Vektor. Ihre Komponenten werden in Ereignisse und Eingabevariablen aufgeteilt, je nach Bedeutung und Erzeugungsmechanismus.

Die Kombination aus dem endlichen Satz von Zuständen und endlichen Satz von Eingangsaktionen formt einen (endlichen) Automat ohne Ausgang. Dieser Automat reagiert auf Eingangsaktionen, indem er seinen aktuellen Zustand auf eine bestimmte Art ändert. Die Regeln, nach denen die Zustände verändert werden, werden als Übergangsfunktion des Automaten bezeichnet.

Was in der automatenbasierten Programmierung als (endlicher) Automat bezeichnet wird, ist im Grunde genommen die Kombination aus "Automat ohne Ausgang" und "Eingangsaktion". Ein solcher Automat reagiert auf die Eingangsaktion, indem er nicht nur seinen Zustand ändert, sondern auch bestimmte Werte bei Ausgängen generiert. Die Regeln für die Generierung von Ausgangsaktionen werden Ausgangsfunktion des Automaten genannt.

Bei der Konzeptionierung eines Systems mit komplexem Verhalten müssen als Ausgangspunkt die bestehenden Kontrollobjekte mit einem bestimmten Satz von Operationen und ein bestimmter Satz von Ereignissen, die in der äußeren Umgebung (Markt) auftreten können, gewählt werden.

In der Praxis basiert die Konzeptionierung häufiger auf Kontrollobjekten und Ereignissen:

  1. Die ursprünglichen Daten der Aufgabe sind nicht nur eine mündliche Beschreibung des angestrebten Systemverhaltens, sondern auch eine (mehr oder weniger) akkurate Festlegung des Satzes von Ereignissen, die aus der äußeren Umgebung in das System kommen, und einer Vielzahl von Anfragen und Befehlen aller Kontrollobjekte.

  2. Ein Satz von Kontrollzuständen wird aufgebaut.

  3. Jeder Anfrage von Kontrollobjekten wird eine entsprechende Eingabevariable des Automaten zugewiesen, während jedem Befehl eine entsprechende Ausgabevariable zugewiesen wird. Der Automat, der ein erforderliches Systemverhalten gewährleisten soll, wird auf Basis von Kontrollzuständen, Ereignissen, Eingabe- und Ausgabevariablen aufgebaut.


6. Besonderheiten und Vorteile des Programms

Die erste Besonderheit eines automatenbasierten Programms ist, dass das Vorhandensein einer äußeren Schleife essentiell ist. Das scheint grundsätzlich nichts Neues zu sein. Das Wichtigste ist hier, dass diese Schleife die einzige im logischen Teil des gesamten Programms sein wird (d. h. neu eingehender Tick).

Die zweite Besonderheit ergibt sich aus der ersten. Jeder Automat beinhaltet eine Switch-Struktur (tatsächlich besteht er fast ausschließlich daraus), die alle Logikfunktionen umfasst. Wenn ein Automat aufgerufen wird, wird die Steuerung an eines der "case"-Labels übertragen, und nach den relevanten Aktionen wird die Arbeit des Automaten (Unterprogramm) bis zum nächsten Start abgeschlossen. Diese Aktionen bestehen aus der Überprüfung der Übergangsbedingungen. Wenn eine bestimmte Bedingung erfüllt wird, werden die entsprechenden Ausgangsfunktionen aufgerufen und der Zustand des Automaten geändert.

Die wichtigste Folge aus allem oben Aufgeführten ist, dass die Umsetzung eines Automaten nicht nur einfach ist, sondern vor allem, dass das Programm ohne viele logische Zwischenvariablen (Flags) auskommt, deren Funktionen in jedem Automaten durch eine mehrwertige Zustandsvariable erfüllt werden.

Die letzte Aussage ist schwer zu glauben, weil wir uns an die Nutzung zahlreicher globaler und lokaler Variablen (Flags) gewöhnt haben, ohne viel darüber nachzudenken. Wie kommen wir ohne sie aus?! Meistens handelt es sich um Flags, die dem Programm signalisieren, dass eine Bedingung erfüllt wird. Das Flag wird (auf TRUE) gesetzt, wenn der Entwickler es als nötig erachtet, aber anschließend (für gewöhnlich erst nachdem das Flag erwünschte Wirkungen ermöglicht, indem es immer TRUE ist) beginnt die mühsame Suche nach einem Punkt an anderer Stelle im Programm, an dem es auf FALSE zurückgesetzt wird.

Klingt vertraut, oder? Sehen Sie sich nun das Beispiel an und Sie werden sehen: Hier werden keine zusätzlichen Variablen genutzt. Die Änderung betrifft nur den Wert der Zustandsnummer, und das auch nur dann, wenn eine logische Bedingung erfüllt wird. Ist das kein würdiger Ersatz für Flags?!

Algorithmen spielen eine wichtige Rolle bei der Erstellung eines logischen Teils eines Programms. Der wichtigste Begriff ist hier "logischer Teil". Als Basis von allem dient hier der Zustand. Ein weiteres wichtiges Wort ist "warten". Somit erhalten wir meiner Meinung nach eine ziemlich gute Definition des "Wartezustands". In diesem Zustand warten wir auf das Erscheinen von Eingangsaktionen (Attributen, Werten oder Ereignissen). Das Warten kann kurz oder lang sein. Oder, in anderen Worten: Es gibt Zustände, die instabil oder stabil sein können.

Die erste Eigenschaft des Zustands ist die Tatsache, dass in dem Zustand auf einen beschränkten Satz von Eingangsaktionen gewartet wird. Jeder Algorithmus (und natürlich auch jedes Programm) verfügt über Eingangs- und Ausgangsinformationen. Ausgangsaktionen lassen sich in zwei Typen einteilen: Variablen (z. B. Operationen für Objekteigenschaften) und Funktionen (z. B. Aufruf der Startfunktion der Anwendung, Berichtsfunktion usw.).

Die zweite Eigenschaft des Zustands ist die Bereitstellung eines Satzes von akkuraten Werten von Ausgangsvariablen. Dies offenbart einen sehr einfachen aber äußerst wichtigen Umstand: Alle Werte von Ausgangsvariablen lassen sich zu jeder Zeit bestimmen, da der Algorithmus (das Programm) sich zu jedem beliebigen Zeitpunkt in einem bestimmten Zustand befindet.

Die Menge der Zustände ist begrenzt, genauso wie die Menge der Werte von Ausgangsvariablen. Die Funktion zum Protokollieren von Übergängen ist nahtlos in die Funktion des Automaten integriert und die Sequenz der Übergänge zwischen Zuständen sowie die Bereitstellung von Ausgangsaktionen können somit immer bestimmt werden.

Die vollständige Liste von Eigenschaften finden Sie in Abschnitt 2. Besonderheiten der vorgeschlagenen Technologie und die vollständige Liste der Vorteile finden Sie in Abschnitt 3. Vorteile der vorgeschlagenen Technologie. Dieser Beitrag kann einfach nicht die riesige Menge an Informationen zu diesem Thema abdecken! Und nach einem eingehenden Studium aller Forschungsliteratur von Anatolij Schalyto sollten alle Fragen zur Theorie direkt an ihn unter shalyto@mail.ifmo.ru gerichtet werden.

Als Anwender seiner wissenschaftlichen Ideen und mit unseren Zielen und Problemen im Hinterkopf gebe ich weiter unten drei Beispiele meiner Implementierung der automatenbasierten Programmiertechnologie an.


7. Beispiele für automatenbasierte Programmierung

7,1. Beispiel fürs Verständnis

Der Zustand ist einfach ein Modus, in dem sich das System befindet. Wasser hat beispielsweise 3 Zustände: fest, flüssig oder gasförmig. Es geht von einem Zustand in einen anderen über, wenn eine Variable – die Temperatur (bei konstantem Druck) – auf es einwirkt.

Nehmen wir an, wir haben ein zeitbasiertes Diagramm der Temperatur (t) (in unserem Fall der Preiswert):

int STATUS=0; // a global integer is by all means always a variable !!! STATUS is a multi-valued flag
//----------------------------------------------------------------------------------------------//
int start() // outer loop is a must
  {
   switch(STATUS)
     {
      case 0:  //--- start state of the program
         if(T>0 && T<100) STATUS=1;
         if(T>=100)       STATUS=2;
         if(T<=0)         STATUS=3;
         break;

      case 1:  //---  liquid
         // set of calculations or actions in this situation (repeating the 1st status -- a loop in automata-based programming) //
         // and calls of other nested automata A4, A5;
         if(T>=100 )      { STATUS=2; /* set of actions when transitioning, calls of other nested automata A2, A3;*/}
         if(T<0)          { STATUS=3; /* set of actions when transitioning, calls of other nested automata A2, A3;*/}
         // logging transitions and actions when the condition is met.
         break;

      case 2:  //--- gas
         // set of calculations or actions in this situation (repeating the 2nd status -- a loop in automata-based programming) //
         // and calls of other nested automata A4, A5;
         if(T>0 && T<100) { STATUS=1; /* set of actions when transitioning, calls of other nested automata A2, A3;*/}
         if(T<=0)         { STATUS=3; /* set of actions when transitioning, calls of other nested automata A2, A3;*/}
         // logging transitions and actions when the condition is met.
         break;

      case 3:  //--- solid
         // set of calculations or actions in this situation (repeating the 3rd status -- a loop in automata-based programming) //
         // and calls of other nested automata A4, A5;
         if(T>0 && T<100) {STATUS=1; /* set of actions when transitioning, calls of other nested automata A2, A3;*/}
         if(T>=100)       {STATUS=2; /* set of actions when transitioning, calls of other nested automata A2, A3;*/}
         // logging transitions and actions when the condition is met.
         break;
     }
   return(0);
  }

Das Programm lässt sich durch das Hinzufügen des Druckparameters P und neuer Zustände und die Einführung einer komplexen Abhängigkeit, die im Diagramm demonstriert wird, komplizierter machen:


Der Automat hat 32 = 9 Übergangsbedingungen, sodass nichts ausgelassen oder übersehen werden kann. Dieser Stil kann auch beim Schreiben von Instruktionen und Gesetzen äußerst praktisch sein! Hier werden keine Schlupflöcher oder Umgehungen von Gesetzen zugelassen – alle Kombinationen von Varianten der Abfolge von Ereignissen müssen abgedeckt und alle Fälle beschrieben sein.

Die automatenbasierte Programmierung stellt an uns die Anforderung, dass wir alles berücksichtigen, auch wenn ansonsten niemand an einige Varianten der Abfolge von Ereignissen gedacht hätte. Deshalb ist sie das Hauptwerkzeug bei der Prüfung von Gesetzen, Instruktionen und Kontrollsystemen auf Konsistenz und Integrität. Es gibt außerdem ein mathematisches Gesetz:

Wenn es N Zustände im System gibt (mit Ausnahme des Starts 0), beträgt die Gesamtmenge der Übergangsbedingungen N2.

Übergangsdiagramm: N = 3 Zustände, die Menge der Übergänge und Schleifen beträgt N2 = 9 (gleich der Menge von Pfeilen).


Wenn die Menge der Variablen im Beispiel anders wäre, dann:


Dies zeigt, dass alle berechneten Werte in der Tabelle exponentiell steigen, d. h. die Konzeptionierung ist ein komplizierter Prozess, der Gründlichkeit bei der Auswahl der Hauptvariablen des Systems erfordert.

Selbst wenn es nur zwei Parameter gibt, ist es sehr schwierig, alles zu beschreiben! Doch in der Praxis ist alles viel einfacher! Je nach Logik und Bedeutung können 50-95 % der Übergänge physisch nicht existieren und die Menge der Zustände ist ebenfalls 60-95 % geringer. Diese Analyse der Logik und Bedeutung senkt den Schwierigkeitsgrad der Beschreibung aller Übergänge und Zustände deutlich.

In komplizierteren Fällen ist es erforderlich, die maximale Anzahl von Zuständen für alle bekannten Eingabe- und Ausgabedaten in einem EA zu berechnen. Die Lösung für dieses Problem liegt in der Anwendung von Kombinatorik und Formeln der Kombination, Permutation, Variation und abzählenden Kombinatorik.

7,2. Relais mit Hysterese

Relais, Auslöser, Register, Zähler, Decoder, Komparatoren und sonstige nichtlineare digitale und analoge Elemente von Kontrollsystemen lassen sich in einem EA sehr bequem programmieren.

  • xmax = 100 – maximaler Anregewert;
  • xmin = -100 – minimaler Anregewert;
  • x = x(t) – Signal am Eingang;
  • Y = Y(t) – Signal am Ausgang.
int   status=0;  // at the beginning of the program we globally assign
//------------------------------------------------------------------//
switch(status)
  {
   case 0: //  start  
      Y=x;
      if(x>xmax)  {status=1;}
      if(x<xmin)  {status=2;}
      break;

   case 1: //++++++++++++++++++++
      if(x>xmax)  Y=x;
      if(x<xmax)  Y=xmin;
      if(x<=xmin) {status=2; Y=xmin;}
      break;

   case 2: //--------------------
      if(x<xmin)  Y=x;
      if(x>xmin)  Y=xmax;
      if(x>=xmax) {status=1; Y=xmax;}
      break;
  }

Charakteristik des Relais:

7,3. Vorlage für 9 Zustände und 81 Varianten der Abfolge von Ereignissen

Y ist der aktuelle Eingangszustand des Automaten von 1 bis 9. Der Wert von Y wird im EA außerhalb des vorliegenden Unterprogramms erzeugt. MEGASTATUS ist der vergangene Zustand von Y.

int MEGASTATUS=0; // at the beginning of the program we globally assign
//---------------------------------------------------------------------//
void A0(int Y) // automaton template
  {
   switch(MEGASTATUS)
     {
      case 0:  // start
          MEGASTATUS=Y;
          break;

      case 1: // it was the past
          // it became current, repeating
          if(Y=1) { /*set of actions in this situation, calls of other nested automata A2, A3, ... */ } // Loop//
          // new current
          if(Y=2) { /* set of actions in this situation */ }
          if(Y=3) { /* set of actions in this situation */ }
          if(Y=4) { /* set of actions in this situation */ }
          if(Y=5) { /* set of actions in this situation */ }
          if(Y=6) { /* set of actions in this situation */ }
          if(Y=7) { /* set of actions in this situation */ }
          if(Y=8) { /* set of actions in this situation */ }
          if(Y=9) { /* set of actions in this situation */ }
          // logging transitions and actions when the condition is met.
          break;

      case 2: // it was the past
          // it has become current
          if(Y=1) { /* set of actions in this situation */ }
          if(Y=2) { /* set of actions in this situation */ } //Loop//
          if(Y=3) { /* set of actions in this situation */ }
          if(Y=4) { /* set of actions in this situation */ }
          if(Y=5) { /* set of actions in this situation */ }
          // e.g. if the transition from 2 to 6 is in essence impossible or does not exist, do not write anything
          if(Y=6) { /* set of actions in this situation */ }
          // the automaton will then be reduced but the automaton template shall be complete to count in everything
          if(Y=7) { /* set of actions in this situation */ }
          if(Y=8) { /* set of actions in this situation */ }
          if(Y=9) { /* set of actions in this situation */ }
          // logging transitions and actions when the condition is met.
          break;

      case 3: // it was the past
          // it has become current
          if(Y=1) { /* set of actions in this situation */ }
          if(Y=2) { /* set of actions in this situation */ }
          if(Y=3) { /* set of actions in this situation */ } //Loop//
          if(Y=4) { /* set of actions in this situation */ }
          if(Y=5) { /* set of actions in this situation */ }
          if(Y=6) { /* set of actions in this situation */ }
          if(Y=7) { /* set of actions in this situation */ }
          if(Y=8) { /* set of actions in this situation */ }
          if(Y=9) { /* set of actions in this situation */ }
          // logging transitions and actions when the condition is met.
          break;

      case 4: // it was the past
          // it has become current
          if(Y=1) { /* set of actions in this situation */ }
          if(Y=2) { /* set of actions in this situation */ }
          if(Y=3) { /* set of actions in this situation */ }
          if(Y=4) { /* set of actions in this situation */ } //Loop//
          if(Y=5) { /* set of actions in this situation */ }
          if(Y=6) { /* set of actions in this situation */ }
          if(Y=7) { /* set of actions in this situation */ }
          if(Y=8) { /* set of actions in this situation */ }
          if(Y=9) { /* set of actions in this situation */ }
          // logging transitions and actions when the condition is met.
          break;

      case 5: // it was the past
          // it has become current
          if(Y=1) { /* set of actions in this situation */ }
          if(Y=2) { /* set of actions in this situation */ }
          if(Y=3) { /* set of actions in this situation */ }
          if(Y=4) { /* set of actions in this situation */ }
          if(Y=5) { /* set of actions in this situation */ } //Loop//
          if(Y=6) { /* set of actions in this situation */ }
          if(Y=7) { /* set of actions in this situation */ }
          if(Y=8) { /* set of actions in this situation */ }
          if(Y=9) { /* set of actions in this situation */ }
          // logging transitions and actions when the condition is met.
          break;

      case 6: // it was the past
          // it has become current
          if(Y=1) { /* set of actions in this situation */ }
          if(Y=2) { /* set of actions in this situation */ }
          if(Y=3) { /* set of actions in this situation */ }
          if(Y=4) { /* set of actions in this situation */ }
          if(Y=5) { /* set of actions in this situation */ }
          if(Y=6) { /* set of actions in this situation */ } //Loop//
          if(Y=7) { /* set of actions in this situation */ }
          if(Y=8) { /* set of actions in this situation */ }
          if(Y=9) { /* set of actions in this situation */ }
          // logging transitions and actions when the condition is met.
          break;

      case 7: // it was the past  
          //it has become current  
          if(Y=1) { /* set of actions in this situation */ }
          if(Y=2) { /* set of actions in this situation */ }
          if(Y=3) { /* set of actions in this situation */ }
          if(Y=4) { /* set of actions in this situation */ }
          if(Y=5) { /* set of actions in this situation */ }
          if(Y=6) { /* set of actions in this situation */ }
          if(Y=7) { /* set of actions in this situation */ } //Loop//
          if(Y=8) { /* set of actions in this situation */ }
          if(Y=9) { /* set of actions in this situation */ }
          // logging transitions and actions when the condition is met.
          break;

      case 8: // it was the past
          // it has become current
          if(Y=1) { /* set of actions in this situation */ }
          if(Y=2) { /* set of actions in this situation */ }
          if(Y=3) { /* set of actions in this situation */ }
          if(Y=4) { /* set of actions in this situation */ }
          if(Y=5) { /* set of actions in this situation */ }
          if(Y=6) { /* set of actions in this situation */ }
          if(Y=7) { /* set of actions in this situation */ }
          if(Y=8) { /* set of actions in this situation */ } //Loop//
          if(Y=9) { /* set of actions in this situation */ }
          // logging transitions and actions when the condition is met.
          break;

      case 9: // it was the past
         // it has become current
          if(Y=1) { /* set of actions in this situation */ }
          if(Y=2) { /* set of actions in this situation */ }
          if(Y=3) { /* set of actions in this situation */ }
          if(Y=4) { /* set of actions in this situation */ }
          if(Y=5) { /* set of actions in this situation */ }
          if(Y=6) { /* set of actions in this situation */ }
          if(Y=7) { /* set of actions in this situation */ }
          if(Y=8) { /* set of actions in this situation */ }
          if(Y=9) { /* set of actions in this situation */ } //Loop//
          // logging transitions and actions when the condition is met.
          break;
     }
   MEGASTATUS=Y;
  }

7,4. Audioplayer-Automat

Sehen wir uns einen einfachen Audioplayer an.

Das Gerät kann sich in 6 Zuständen befinden:

  1. Bereit;
  2. Kein Track;
  3. Abspielen;
  4. Vorspulen;
  5. Zurückspulen;
  6. Pause.

Das Kontrollsystem des Audioplayers stellt einen Automaten dar. Das Drücken von Knöpfen wird als Ereignis betrachtet, das sich auf den Automaten auswirkt. Übergänge zwischen Tracks, Abspielen, Anzeigekontrolle usw. sind Ausgangsaktionen.

switch(STATUS)
  {
   case 0: //--- "Ready"
      if(Event == 3) { STATUS = 3; } //«>>» button pressed
      if(Event == 6) { STATUS = 1; } //Audio file not found 
      if(Event == 1) { STATUS = 2; } //«PLAY» button pressed
   
      z1();  // Set the indicator to the initial state
      break;

   case 1: //--- "No Track"
      z6();  // Give the «No Track» message
      break;

   case 2: //--- "Playing"
      if(Event == 4) { STATUS = 4; } //«<<» button pressed
      if(Event == 5) { STATUS = 5; } //«PAUSE»( | | ) button pressed
      if(Event == 3) { STATUS = 3; } //«>>» button pressed
      if(Event == 2) { STATUS = 0; } //«STOP» button pressed
      z2(); // Playing
      break;

   case 3: //--- "Fast-Forward"
      z3();  // Next track
      { STATUS=2; }
      break;

   case 4: //--- "Rewind"
      z4(); // Previous track
      { STATUS=2; }
      break;

   case 5: //--- "Pause"
      if(Event == 5) { STATUS = 2; } //«PAUSE» button pressed
      if(Event == 1) { STATUS = 2; } //«PLAY» button pressed
      if(Event == 2) { STATUS = 0; } //«STOP» button pressed
      if(Event == 3) { STATUS = 3; } //«>>» button pressed
      if(Event == 4) { STATUS = 4; } //«<<» button pressed
      z5(); //Pause
      break;
  }

In der Theorie könnte dieser Automat 36 Übergangsvarianten enthalten, doch nur 15 existieren tatsächlich und alle Details finden Sie in der vom Autor bereitgestellten Beschreibung.


8. А.А. Schalytos Empfehlungen für die Durchführung von Projekten

Vollständige Informationen zur Erstellung und Formulierung der Projektdokumentation finden Sie unter http://project.ifmo.ru/books/3. In diesem Beitrag führe ich nur einen kurzen Auszug auf:

  1. Das Buch "Logische Steuerung. Methoden zur Hardware- und Softwareumsetzung von Algorithmen. SPb.: Nauka, 2000" von A.A. Schalyto, das unter der angegebenen Adresse im Bereich "Bücher" gefunden werden kann, kann als Prototyp herangezogen werden. Es stellt die Informationen korrekt dar, da es durch den ältesten und angesehensten Verlag Russlands herausgegeben wurde.
  2. Die Einleitung muss eine Grundlage für die Relevanz des gewählten Themas bilden, die zu betrachtende Aufgabe kurz umreißen und die Programmiersprache und das Betriebssystem, die für das Projekt genutzt wurden, nennen.
  3. Eine detaillierte verbale Beschreibung der vorliegenden Aufgabe muss im Abschnitt "Aufgabenbeschreibung" zusammen mit Abbildungen, Diagrammen und Screenshots, die die beschriebene Aufgabe erklären, enthalten sein.
  4. Bei der Nutzung objektorientierter Programmierung muss der Abschnitt "Konzeptionierung" ein Diagramm der Klassen enthalten. Die wichtigsten Klassen müssen detailliert beschrieben werden. Es wird empfohlen, ein "Blockdiagramm der Klasse" für jede der Klassen zu erstellen, das ihr Interface und ihre Methoden präsentiert, und anzugeben, welche davon automatenbasierte Methoden darstellen.
  5. Im Abschnitt "Automaten" müssen drei Dokumente für jeden Automat enthalten sein: eine verbale Beschreibung, ein Verknüpfungsdiagramm und ein Übergangsdiagramm.
  6. Eine verbale Beschreibung muss möglichst detailliert sein, doch da es schwierig ist, das Verhalten eines komplexen Automaten zu beschreiben, stellt sie meistens eine "Erklärung der Absichten" dar.
  7. Das Verknüpfungsdiagramm des Automaten liefert eine detaillierte Beschreibung seines Interfaces. Der linke Teil des Diagramms muss Folgendes enthalten:
    • Datenquellen;
    • vollständiger Name jeder Eingabevariable;
    • vollständiger Name jedes Ereignisses;
    • Prädikate mit Zustandsnummern anderer Automaten, die im vorliegenden Automat als Eingangsaktionen verwendet werden. Bspw. kann das Prädikat Y8 == 6 verwendet werden, das den Wert Eins annimmt, sobald der achte Automat in den sechsten Zustand übergeht;
    • als x gekennzeichnete Eingabevariablen mit entsprechenden Indizes;
    • als e gekennzeichnete Ereignisse mit entsprechenden Indizes;
    • Variablen zum Speichern von Zuständen des Automaten mit der Nummer N, gekennzeichnet als YN.

    Der rechte Teil des Diagramms muss Folgendes enthalten:
    • als z gekennzeichnete Ausgabevariablen mit entsprechenden Indizes;
    • vollständiger Name jeder Ausgabevariable;
    • Ereignisse, die durch den vorliegenden Automaten generiert werden (falls zutreffend);
    • vollständiger Name jedes generierten Ereignisses;
    • Datenempfänger.
  8. Wenn komplexe Berechnungsalgorithmen in Knoten oder Übergängen genutzt werden, erklärt der Abschnitt "Berechnungsalgorithmen" die Auswahl der Algorithmen und führt ihre Beschreibungen auf (einschließlich der mathematischen Beschreibung). Diese Algorithmen werden durch die Variablen x und z gekennzeichnet, je nachdem, ob die Berechnungen am Eingang oder am Ausgang stattfinden.
  9. Besonderheiten der Programmumsetzung müssen im Abschnitt "Umsetzung" dargelegt werden. Insbesondere muss dieser Abschnitt eine Vorlage für die formale und isomorphe Umsetzung von Automaten enthalten. Umsetzungen von Automaten müssen auch hier aufgeführt werden.
  10. Der Abschnitt "Fazit" behandelt die Vor- und Nachteile des abgeschlossenen Projekts. Er kann auch Möglichkeiten aufführen, das Projekt zu verbessern.


9. Fazit

Ich möchte Sie alle ermutigen:

  • diese neue Herangehensweise an die Programmierung zu erforschen.
  • diese völlig neue und äußerst interessante Herangehensweise an die Programmierung Ihrer Ideen und Handelsstrategien umzusetzen.

Ich hoffe, dass die automatenbasierte Programmierung:

  • mit der Zeit zum Standard bei der Programmierung und Konzeptionierung für alle Händler und sogar die Entwickler der MetaQuotes Language wird.
  • die Basis für komplexe Entscheidungen bei der Konzeptionierung von EAs bilden wird.
  • sich in Zukunft zu einer neuen Sprache – MetaQuotes Language 6 –, die die automatenbasierte Herangehensweise an die Programmierung unterstützt, und einer neuen Plattform – MetaTrader 6 – entwickeln wird.

Wenn alle Trading-Entwickler diesen Programmieransatz befolgen, lässt sich das Ziel eines verlustfreien EAs erreichen. Dieser erste Beitrag ist mein Versuch, Ihnen dieses Ventil für Kreativität und Forschung auf dem Gebiet der automatenbasierten Konzeptionierung und Programmierung als Impuls für neue Erfindungen und Entdeckungen zu zeigen.

Und eines noch: Ich stimme dem Artikel des Verfassers völlig zu und bin der Meinung, dass es wichtig ist, ihn Ihnen in gekürzter Form zur Verfügung zu stellen (vollständiger Text unter http://is.ifmo.ru/works/open_doc/):

Warum Quellcodes keine Lösung für das Verstehen von Programmen sind

Die wichtigste praktische Frage in der Programmierung ist die Frage des Verstehens von Programmcodes. Es ist immer gut, die Quellcodes griffbereit zu haben, doch das Problem ist, dass das alleine oft nicht reicht. Für gewöhnlich wird zusätzliche Dokumentation benötigt, um sich ein Verständnis eines nichttrivialen Programms anzueignen. Dieses Bedürfnis steigt mit steigender Menge an Code exponentiell.

Programmcode-Analysen, die die ursprünglichen Konzeptentscheidungen von Entwicklern rekonstruieren und zum Verständnis von Programmen beitragen sollen, sind zwei wichtige Zweige der Programmiertechnologie, deren Existenz mit der Unzulänglichkeit von Quellcodes für das Verstehen von Programmen Hand in Hand geht.

Jeder, der je an einem großen Projekt zur Software-Rekonstruierung beteiligt war, wird sich immer an das Gefühl von Hilflosigkeit und Verwirrung erinnern, das sich einstellt, wenn Sie erstmals einen Haufen von schlecht dokumentierten (wenn auch nicht immer schlecht geschriebenen) Quellcodes sehen. Die Verfügbarkeit von Quellcodes ist keine große Hilfe, wenn man nicht an die wichtigsten Entwickler herankommt. Wenn das Programm in einer maschinennahen Sprache geschrieben und dazu auch schlecht dokumentiert wurde, verstecken sich die wichtigen Konzeptentscheidungen für gewöhnlich in Programmierungsdetails und müssen rekonstruiert werden. In solchen Fällen kann der Wert einer höher angesiedelten Dokumentation wie der Interface-Spezifikation und Beschreibung der Architektur höher sein als der Wert des Quellcodes selbst.

Die Feststellung, dass Quellcodes ungeeignet sind, um Programme zu verstehen, führte zu Versuchen, den Code und eine höher angesiedelte Dokumentation zu kombinieren.

Wenn Sie die frühen Phasen des Projekts verpassen, hindern die Komplexität und die Menge an Arbeit Sie daran, die Quellcodes zu verstehen, sofern keine höher angesiedelte Dokumentation vorhanden ist. Den "prähistorischen" Code in Abwesenheit der ursprünglich am Projekt beteiligten Programmierer und ohne angemessene Dokumentation, die es möglich machen würden, die relevanten Architekturentscheidungen zu finden, zu verstehen, ist vermutlich eine der schwierigsten Herausforderungen, auf die Programmierer stoßen.


Warum Programmen ein Konzept fehlt

Während das Fehlen von Quellcodes also schlecht sein kann, kann ihr Vorhandensein ebenfalls schlecht sein. Was fehlt also noch für "...und sie lebten glücklich bis ans Ende ihrer Tage"? Die Antwort ist einfach: eine detaillierte und akkurate Konzeptdokumentation, die die Programmdokumentation als einen ihrer Bestandteile umfasst.

Brücken, Straßen und Wolkenkratzer werden für gewöhnlich nicht ohne Dokumentation gebaut, was für Programme nicht zutrifft.

Die Situation, die in der Programmierung entstanden ist, kann folgendermaßen beschrieben werden: "Wenn Bauarbeiter Gebäude so bauen würden, wie Programmierer Programme schreiben, würde der erste Specht die Zivilisation zerstören."

Warum wird für Hardware so viel detaillierte und klare Konzeptdokumentation veröffentlicht, die von einem durchschnittlichen Spezialisten noch Jahre nach ihrer Veröffentlichung relativ einfach verstanden und modifiziert werden kann, während eine solche Dokumentation für Software entweder nicht vorhanden ist oder rein formal verfasst ist, sodass hochqualifizierte Spezialisten benötigt werden, um sie zu modifizieren (wenn der Entwickler abwesend ist)?

Anscheinend lässt sich diese Situation erklären, wie folgt. Erstens: Entwicklung und Herstellung von Hardware sind zwei unterschiedliche Prozesse, die von verschiedenen Organisationen durchgeführt werden. Deshalb wird der Entwicklungstechniker den Rest seines Lebens im "Werk" verbringen, wenn die Qualität der Dokumentation schlecht ist, was sicher nicht seinem Wunsch entspricht. Wenn es nun um Softwareentwicklung geht, ist die Situation eine andere, da in diesem Fall der Softwareentwickler und der Hersteller für gewöhnlich ein und dasselbe Unternehmen sind und ihre Inhalte deshalb unabhängig von der Liste von Dokumenten für gewöhnlich ziemlich oberflächlich sind.

Zweitens: Hardware ist "hart", Software ist "weich". Das macht es einfacher, Programme zu modifizieren, gibt aber keinen Anlass dazu, überhaupt keine Konzeptdokumentation zu veröffentlichen. Es ist bekannt, dass die meisten Programmierer pathologisch unwillig sind, Dokumentation zu lesen, geschweige denn, zu schreiben.

Die aktuellen Erfahrungen lassen darauf schließen, dass so gut wie kein neu ausgebildeter Programmierer, sogar der schlaueste unter ihnen, Konzeptdokumentation erstellen kann. Und obwohl die meisten von ihnen lange und komplexe Mathematikkurse belegt und bestanden haben, haben diese so gut wie keinen Einfluss auf ihre Logik und Genauigkeit beim Schreiben von Dokumentation. Sie können verschiedene Schreibweisen für denselben Gegenstand in der gesamten Dokumentation (unabhängig von ihrer Größe) nutzen und den Gegenstand Birne, Glühbirne, Lampe oder Lämpchen nennen, nach eigenem Belieben groß oder klein geschrieben. Stellen Sie sich vor, was passiert, wenn sie ihrer Fantasie freien Lauf lassen!

Anscheinend geschieht dies deshalb, weil der Compiler beim Programmieren Inkonsistenzen kennzeichnet, während die Konzeptdokumentation ohne jegliche Vorgaben geschrieben wird.

Das Problem der Qualität von Softwaredokumentation wird allmählich zu einem Problem mit immer höherer sozialer Bedeutung. Die Softwareentwicklung wird mit ihrem stark ausgeprägten Profitwillen dem Showbusiness immer ähnlicher. Alles wird in furchtbarer Eile gemacht, ohne darüber nachzudenken, was in Zukunft aus dem Produkt werden wird. Wie das Showbusiness misst auch die Programmierung alles mit den Begriffen "Gewinn und Verlust" anstatt "gut und schlecht". In den meisten Fällen ist eine gute Technologie nicht diejenige, die tatsächlich gut ist, sondern diejenige, die Gewinne abwirft.

Die fehlende Bereitschaft, Konzeptdokumentation zu schreiben, hängt vermutlich auch damit zusammen, dass der Autor unverzichtbarer wird, je verschlossener (undokumentierter) das Projekt ist.

Diese Arbeitsweise weitet sich leider auf die Entwicklung von Software für hochkritische Systeme aus. Das liegt größtenteils daran, dass Programme in den meisten Fällen geschrieben und nicht konzeptioniert werden. "Beim Konzeptionieren wird jede Technik, die komplexer als CRC-Karten oder Anwendungsfalldiagramme ist, als zu komplex betrachtet und wird deshalb nicht verwendet. Ein Programmierer kann sich immer weigern, eine bestimmte Technologie anzuwenden, indem er seinem Vorgesetzten meldet, dass er die Deadline möglicherweise nicht einhalten können wird."

Das führt zu Situationen, in denen sogar die "Benutzer Fehler in der Software als nichts Außergewöhnliches sehen".

Die Auffassung ist weit verbreitet, dass Konzeptionierung und ordnungsgemäße Dokumentation bei großen Gebäuden vorhanden sein müssen, nicht bei Software.

Als Fazit halten wir fest, dass diese Situation in der Programmierung nicht immer geherrscht hat – bei der Nutzung früher Großcomputer wurden Programme entweder konzeptioniert oder sehr sorgfältig geschrieben, da der nächste Versuch im Falle eines Fehlers frühestens am nächsten Tag stattfinden konnte. Also hat uns der technische Fortschritt eine sorglosere Programmierung beschert.


Leider lassen sich unsere Probleme und Sorgen nicht auf der Webseite des Fachbereichs auffinden, in dem A.A. Schalyto arbeitet. Dort hat man eigene Probleme und Ziele und ist mit unseren Konzepten und Definitionen weder vertraut noch ihrer bewusst, deshalb gibt es keine Beispiele, die für unser Thema relevant sind.


Die wichtigsten Bücher/Lehrbücher von A.A. Schalyto:

  1. Automatenbasierte Programmierung. http://is.ifmo.ru/books/_book.pdf
  2. Nutzung von Flussdiagrammen und Übergangsdiagrammen bei der Umsetzung von logischen Kontrollalgorithmen. http://is.ifmo.ru/download/gsgp.pdf
  3. Automatenbasierte Programmierung. http://is.ifmo.ru/works/_2010_09_08_automata_progr.pdf
  4. Umwandlung von iterativen Algorithmen in automatenbasierte Algorithmen. http://is.ifmo.ru/download/iter.pdf
  5. Switch-Technologie: Automatenbasierte Herangehensweise an die Entwicklung von Software für reaktive Systeme. http://is.ifmo.ru/download/switch.pdf
  6. Automatenbasierte Programmkonzeption. Algorithmisierung und Programmierung von logischen Kontrollaufgaben. http://is.ifmo.ru/download/app-aplu.pdf
  7. Nutzung des genetischen Algorithmus zum Entwerfen eines Autopiloten für ein vereinfachtes Hubschraubermodell. http://is.ifmo.ru/works/2008/Vestnik/53/05-genetic-helicopter.pdf
  8. Explizite zustandsbasierte Programmierung. http://is.ifmo.ru/download/mirpk1.pdf
  9. Algorithmisierung und Programmierung für logische Kontrollsysteme und reaktive Systeme. http://is.ifmo.ru/download/arew.pdf
  10. Objektorientierte Herangehensweise an die automatenbasierte Programmierung. http://is.ifmo.ru/works/ooaut.pdf
  11. Grafische Schreibweise für die Vererbung automatenbasierter Klassen. http://is.ifmo.ru/works/_12_12_2007_shopyrin.pdf
  12. Programmieren in... 1 (einer) Minute. http://is.ifmo.ru/progeny/1minute/?i0=progeny&i1=1minute

Projekte:

  1. Modellieren der Arbeit von Geldautomaten. http://is.ifmo.ru/unimod-projects/bankomat/
  2. Modellieren des Steuerprozesses von Kernreaktoren. http://is.ifmo.ru/projects/reactor/
  3. Steuerungssystem eines Aufzugs. http://is.ifmo.ru/projects/elevator/
  4. Automatenbasierte Entwicklung eines Kontrollsystems für eine Kaffeemaschine. http://is.ifmo.ru/projects/coffee2/
  5. Konzeptionierung und Erforschung von Automaten für das Fahren. http://is.ifmo.ru/projects/novohatko/
  6. Modellieren einer Digitalkamera mithilfe automatenbasierter Programmierung. http://project.ifmo.ru/shared/files/200906/5_80.pdf
  7. Automatenbasierte Programmierung für die Modellierung eines Multiagent-Systems für autonome Fahrzeuge. http://project.ifmo.ru/shared/files/200906/5_41.pdf
  8. Visuelles System für die Lösung eines Zauberwürfels. http://is.ifmo.ru/projects/rubik/

und weitere interessante Artikel und Projekte: http://project.ifmo.ru/projects/http://is.ifmo.ru/projects_en/ und http://is.ifmo.ru/articles_en/.


P.S.

Die Anzahl der verschiedenen möglichen Ereignisse eines Zauberwürfels ist (8! × 38−1) × (12! × 212−1)/2 = 43.252.003.274.489.856.000. Doch diese Zahl berücksichtigt nicht die Tatsache, dass die zentralen Quadrate unterschiedliche Ausrichtungen haben können.

Unter Berücksichtigung der möglichen Ausrichtungen der zentralen Quadrate wird die Anzahl der Ereignisse 2048 Mal so groß, d. h. 88.580.102.706.155.225.088.000.

Der Forexmarkt und die Aktienbörse haben nicht so viele mögliche Varianten der Abfolge von Ereignissen, aber mit ihnen verbundene Aufgaben lassen sich in 100-200 Schritten unter Zuhilfenahme dieses Programmierparadigmas leicht lösen. Es stimmt! Der Markt und die EAs stehen in einem ständigen Konkurrenzkampf. Es ist, als würde man Schach spielen, bei dem niemand die künftigen Züge des Gegners kennt (genauso wie wir). Allerdings gibt es beeindruckende Computerprogramme wie Rybka (ein sehr starkes Schachprogramm) auf Basis von Alpha-Beta-Pruning-Algorithmen.

Ich hoffe, dass diese Erfolge anderer in anderen Bereichen der Programmierung bei ihnen für Energie und Engagement für unsere Arbeit sorgen! Obwohl wir natürlich alle wissen, dass wir nichts wissen.


Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/446

Die aktivsten Mitglieder der MQL5.community wurden mit iPhones belohnt! Die aktivsten Mitglieder der MQL5.community wurden mit iPhones belohnt!
Nachdem wir beschlossen hatten, die herausstechendsten Mitglieder von MQL5.com zu belohnen, haben wir die wichtigsten Kriterien festgelegt, um den Beitrag jedes Teilnehmers zur Entwicklung der Community zu bestimmen. Als Ergebnis haben wir die folgenden Sieger, die die meisten Beiträge auf der Webseite verfasst haben investeo (11 Beitrge) und victorg (10 Beiträge) und die ihre Programme an die Code Base gesendet haben GODZILLA (340 Programme), Integer (61 Programme) und abolk (21 Programme).
OpenCL: Vom naiven zum aufschlussreicheren Programmieren OpenCL: Vom naiven zum aufschlussreicheren Programmieren
Dieser Beitrag konzentriert sich auf bestimmte Optimierungsmöglichkeiten, die sich eröffnen, wenn die zugrunde liegende Software, auf der das OpenCL-Kernel ausgeführt wird, zumindest ein bisschen berücksichtigt wird. Die Zahlen, die wir hier erhalten, sind alles andere als Spitzenwerte, doch auch sie lassen schon darauf schließen, dass mithilfe der hier und jetzt verfügbaren Ressourcen (die OpenCL-API in der Form, in der sie von den Entwicklern des Terminals implementiert wurde, erlaubt nicht die Steuerung bestimmter Parameter, die für die Optimierung wichtig sind, insbesondere die Größe von Arbeitsgruppen) der Performance-Gewinn über die Ausführung des Host-Programms beträchtlich ist.
Visuelle Optimierung von Indikator und Signal Rentabilität Visuelle Optimierung von Indikator und Signal Rentabilität
Dieser Artikel ist eine Fortsetzung und Weiterentwicklung meines vorherigen Artikels "Visuelles Testen der Rentabilität der Indikatoren und Benachrichtigungen". Nachdem ich einige Interaktivität zu dem Parameter Änderungsprozess hinzugefügt und die Studienziele überarbeitet habe, schaffte ich es ein neues Werkzeug zu erhalten, das nicht nur die potentiellen Handelsergebnisse auf Grundlage der verwendeten Signale zeigt, sondern Ihnen ermöglicht sofort ein Layout von Trades, Kontostand-Chart und Endergebnissen des Handels zu erhalten, durch verschieben virtueller Slider (Schieberegler), die als Steuerung für Signal-Parameterwerte in de Hauptchart fungieren.
OpenCL: Die Brücke zu parallelen Welten OpenCL: Die Brücke zu parallelen Welten
Ende Januar 2012 kündigte die Softwareentwicklungsfirma, die hinter der Entwicklung von MetaTrader 5 steht, die native Unterstützung von OpenCL in MQL5 an. Dieser Beitrag legt anhand eines anschaulichen Beispiels die Programmiergrundsätze für OpenCL in der MQL5-Umgebung dar und liefert einige Beispiele für die "naive" Optimierung des Programms, um die Betriebsgeschwindigkeit zu erhöhen.