Machine learningZorro can utilize included or external machine learning algorithms, for instance from R packages, for applying 'artificial intelligence' to algorithmic trading. Three internal algorithms for price prediction are available: a decision tree, a simple neural network, and a signal pattern learning system. They generate trading rules separately for any WFO cycle, asset, algo, and long or short trades. You can also provide your own function for training an individual model, or use functions from R or Python packages. An introduction into various machine learning methods can be found on Financial Hacker. The advise functions are used to implement a machine learning algorithm just like a standard indicator: adviseLong (int Method, var Objective, var Signal0, var Signal1, var Signal2, ..., var Signal19): varadviseShort (int Method, var Objective, var Signal0, var Signal1, var Signal2, ... var Signal19): varadviseLong (int Method, var Objective, var* Signals, int NumSignals): varadviseShort (int Method, var Objective, var* Signals, int NumSignals): varCall a machine learning algorithm for training or for prediction. In [Train] mode the function trains the algorithm to predict either a subsequent trade return or a training target (Objective). In [Test] or [Trade] mode the function calls the algorithm and returns the predicted value. Depending on algorithm, training can generate a binary model or a prediction function in C code that is stored in the Data folder. The only difference of the ..Long and ..Short variants is that they can train on the returns of long and short trades; otherwise they are identical. They can thus alternatively be used for generating two different models per algo/asset component. Parameters:
Returns:
[Train] mode: 100 when trade results are to be trained,
i.e. the RETURNS flag is set or Objective is zero. Otherwise 0. DTREE (Decision Tree)A decision tree is a tree-like graph of decisions by comparing signals with fixed values. The values and the tree structure are generated in the training run. For this the training process iterates through the sets of signals and finds the signal values with the lowest information entropy. These values are then used to split the data space in a profitable and a non profitable part, then the process continues with iterating through the parts. Details about the decision tree algorithm can be found in books about machine learning. The signals should be normalized roughly to the -100..100 range for best precision. They should be carefully selected so that the displayed prediction accuracy is well above 60% in all WFO cycles. Decision trees work best with signals that are independent of each other. They do not work very well when the prediction depends on a linear combination of the signals. In order to reduce overfitting, the resulting trees are pruned by removing non-predictive signals. The output of the tree is a number between -100 .. +100 dependent on the predictive quality of the current signal combination. The decision tree functions are stored in C source code in the \Data\*.c file. The functions are automatically included in the strategy script and used by the advise function in test and trade mode. They can also be exported for using them in strategy scripts or expert advisors of other platforms. The example below is a typical Zorro-generated decision tree: int EURUSD_S(var* sig) The advise() call used 5 signals, of which the first and the last one - sig[0] and sig[4] - had no predictive power, and thus were pruned and do not appear in the tree. Unpredictive signals are displayed in the message window. Example of a script for generating a decision tree: void run() { BarPeriod = 60; LookBack = 150; TradesPerBar = 2; if(Train) Hedge = 2; set(RULES|TESTNOW); // generate price series vars H = series(priceHigh()), L = series(priceLow()), C = series(priceClose()); // generate some signals from H,L,C in the -100..100 range var Signals[2]; Signals[0] = (LowPass(H,1000)-LowPass(L,1000))/PIP; Signals[1] = 100*FisherN(C,100); // train and trade the signals Stop = 4*ATR(100); TakeProfit = 4*ATR(100); if(adviseLong(DTREE,0,Signals,2) > 0) enterLong(); if(adviseShort(DTREE,0,Signals,2) > 0) enterShort(); } PERCEPTRONA perceptron, also called a logistic regression function, is a simple neural net consisting of one neuron with one output and up to 20 signal inputs. It calculates its predictions from a linear combination of weighted signals. It has some similarity to the polyfit algorithm, but with arbitrary variables instead of powers of a single variable, and with a binary output. A short perceptron algorithm description can be found on the machine learning overview. The signal weights are generated in the training run for producing the best possible prediction. The signals should be in the single digit range, like -1...1. The perceptron algorithm works best when the weighted sum of the signals has predictive power. It does not work well when the prediction requires a nonlinear signal combination, i.e., when trade successes and failures are not separated by a straight plane in the signal space. A classical example of a function that a perceptron cannot emulate is a logical XOR. Often a perceptron can be used where a decision tree fails, and vice versa. The perceptron learning algorithm generates prediction functions in C source code in the \Data\*.c file. The functions are automatically included in the strategy script and used by the advise function in test and trade mode. They can also be exported for using them in strategy scripts or expert advisors of other platforms. The output is >0 for a positive or <0 for a negative prediction. The output magnitude is the probability associated with the prediction, in percent, e.g., 70 for 70% estimated probability. A generated perceptron function with 3 signals and binary output looks like this: int EURUSD_S(var* sig) In FUZZY mode the output magnitude is equivalent to the prediction strength, thus allowing to ignore signals below a threshold. The scaling factor, 2.50 in the example below, is calculated so that the average perceptron return value of the training set has a magnitude of 50. Example of a fuzzy perceptron: int EURUSD_S(var* sig) Signals that do not contain predictive market information get a weight of 0. PATTERN (Pattern Analyzer)The pattern analyzer is an intelligent version of classic candle pattern indicators. It does not use predefined patterns, but learns them from historical price data. It's normally fed with up to 20 open, close, high or low prices of a number of candles. It compares every signal with every other signal, and uses the comparison results - greater, smaller, or equal - for classifying the pattern. The signals can be divided into groups with the PATTERN+2 .. PATTERN+6 methods. They divide the signals into up to six pattern groups and only compare signals within the same group. This is useful when, for instance, only the first two candles and the last two candles of a 3-candle pattern should be compared with each other, but not the first candle with the third candle. PATTERN+2 requires an even number of signals, of which the first half belongs to the first and the second half to the second group. PATTERN+3 likewise requires a number of signals that is divisible by 3, and so on. Pattern groups can share signals - for instance, the open, high, low, and close of the middle candle can appear in the first as well as in the second group - as long as the total number of signals does not exceed 20. Aside from the grouping, Zorro makes no assumptions of the signals and their relations. Therefore the pattern analyzer can be also used for other signals than candle prices. All signals within a pattern group should have the same unit for being comparable, but different groups can have different units. For candle patterns, usually the high, low, and close of the last 3 bars are used for the signals - the open is not needed as it's normally identical with the close of the previous candle. More signals, such as the moving average of the price, can be added for improving the prediction (but in most cases won't). For simple patterns with few signals, the pattern analyzer can generate direct pattern finding functions in plain C source code in the \Data\*.c file. These functions are automatically included in the strategy script and used by the advise function in test and trade mode. They can also be exported to other platforms. They find all patterns that occurred 4 or more times in the training data set and had a positive profit expectancy. They return the pattern's information ratio - the ratio of profit mean to standard deviation - multiplied with 100. The better the information ratio, the more predictive is the pattern. A typical pattern finding function with 12 signals looks like this: int EURUSD_S(float* sig) { if(sig[1]<sig[2] && eqF(sig[2]-sig[4]) && sig[4]<sig[0] && sig[0]<sig[5] && sig[5]<sig[3] && sig[10]<sig[11] && sig[11]<sig[7] && sig[7]<sig[8] && sig[8]<sig[9] && sig[9]<sig[6]) return 19; if(sig[4]<sig[1] && sig[1]<sig[2] && sig[2]<sig[5] && sig[5]<sig[3] && sig[3]<sig[0] && sig[7]<sig[8] && eqF(sig[8]-sig[10]) && sig[10]<sig[6] && sig[6]<sig[11] && sig[11]<sig[9]) return 170; if(sig[1]<sig[4] && eqF(sig[4]-sig[5]) && sig[5]<sig[2] && sig[2]<sig[3] && sig[3]<sig[0] && sig[10]<sig[7] && eqF(sig[7]-sig[8]) && sig[8]<sig[6] && sig[6]<sig[11] && sig[11]<sig[9]) return 74; if(sig[1]<sig[4] && sig[4]<sig[5] && sig[5]<sig[2] && sig[2]<sig[0] && sig[0]<sig[3] && sig[7]<sig[8] && eqF(sig[8]-sig[10]) && sig[10]<sig[11] && sig[11]<sig[9] && sig[9]<sig[6]) return 143; if(sig[1]<sig[2] && eqF(sig[2]-sig[4]) && sig[4]<sig[5] && sig[5]<sig[3] && sig[3]<sig[0] && sig[10]<sig[7] && sig[7]<sig[8] && sig[8]<sig[6] && sig[6]<sig[11] && sig[11]<sig[9]) return 168; .... return 0; } The eqF function in the code above checks if two signals are equal. Signals that differ less than the FuzzyRange are considered equal. There are two additional special methods for the pattern analyzer. The FUZZY method generates a pattern finding function that also finds patterns that can slightly deviate from the profitable patterns in the training data set. It gives patterns a higher score when they 'match better'. The deviation can be set up with FuzzyRange. A typical fuzzy pattern finding function looks like this: int EURUSD_S(float* sig) { double result = 0.; result += belowF(sig[1],sig[4]) * belowF(sig[4],sig[2]) * belowF(sig[2],sig[5]) * belowF(sig[5],sig[3]) * belowF(sig[3],sig[0]) * equF(sig[10],sig[11]) * belowF(sig[11],sig[7]) * belowF(sig[7],sig[8]) * belowF(sig[8],sig[9]) * belowF(sig[9],sig[6]) * 19; result += belowF(sig[4],sig[5]) * belowF(sig[5],sig[1]) * belowF(sig[1],sig[2]) * belowF(sig[2],sig[3]) * belowF(sig[3],sig[0]) * belowF(sig[10],sig[7]) * belowF(sig[7],sig[11]) * belowF(sig[11],sig[8]) * belowF(sig[8],sig[9]) * belowF(sig[9],sig[6]) * 66; result += belowF(sig[4],sig[1]) * belowF(sig[1],sig[2]) * belowF(sig[2],sig[0]) * belowF(sig[0],sig[5]) * belowF(sig[5],sig[3]) * belowF(sig[10],sig[11]) * belowF(sig[11],sig[7]) * belowF(sig[7],sig[8]) * belowF(sig[8],sig[6]) * belowF(sig[6],sig[11]) * 30; result += belowF(sig[1],sig[4]) * belowF(sig[4],sig[2]) * belowF(sig[2],sig[5]) * belowF(sig[5],sig[3]) * belowF(sig[3],sig[0]) * belowF(sig[7],sig[10]) * belowF(sig[10],sig[11]) * belowF(sig[11],sig[8]) * belowF(sig[8],sig[6]) * belowF(sig[6],sig[9]) * 70; result += belowF(sig[4],sig[5]) * belowF(sig[5],sig[1]) * belowF(sig[1],sig[2]) * belowF(sig[2],sig[3]) * belowF(sig[3],sig[0]) * belowF(sig[7],sig[10]) * belowF(sig[10],sig[8]) * belowF(sig[8],sig[11]) * belowF(sig[11],sig[9]) * belowF(sig[9],sig[6]) * 108; ... return result; } The belowF function is described on the Fuzzy Logic page. The FAST method does not generate C code; instead it generates a list of patterns that are classified with alphanumeric names. For finding a pattern, it is classified and its name compared with the pattern list. This is about 4 times faster than the pattern finding function in C code, and can also handle bigger and more complex patterns with up to 20 signals. It can make a remarkable difference in backtest time or when additional parameters have to be trained. A pattern name list looks like this (the numbers behind the name are the information ratios): /* Pattern list for EURUSD_S The FAST method cannot be used in combination with FUZZY or with FuzzyRange. But the FAST as well as the FUZZY method can be combined with pattern groups (e.g., PATTERN+FAST+2). The find rate of the pattern analyzer can be adjusted with two variables: PatternCountThe minimum number of occurrences of the found patterns in the analyzed price curve; default = 4. PatternRateThe minimum win rate of the found patterns, in percent; default = 50. An example of a pattern trading script can be found in Workshop 7. NEURAL (General Machine Learning)The NEURAL method uses an external machine learning library, for instance a support vector machine, random forest, or a deep learning neural network for predicting the next price or next trade return in an algo trading system. Many machine learning libraries are available in R packages or Python libraries; therefore the NEURAL method will often call R or Python functions for training and prediction. But any DLL-based machine learning library can be used as long as the neural function - see below - is adapted to it. neural (int Status, int Model, int NumSignals, void* Data): varThis function is automatically called several times during the training, test, or trade process. It has access to all global and predefined variables. Its behavior depends on Status:
Model is the number of the trained model, for instance a set of decision rules, or a set of weights of a neural network, starting with 0. When several models are trained for long and short predictions and for different assets or algos, the index selects the suited model. The number of models is therefore normally equal to the number of advise calls per run cycle. All trained models are saved to a *.ml file at the end of every WFO cycle. In R, the models are normally stored in a list of lists and accessed through their index (e.g., Models[[model+1]]). Any additional parameter set generated in the training process - for instance, a set of normalization factors, or selection masks for the signals - can be saved as part of the model. The NumSignals parameter is the number of signals passed to the advise function. It is normally identical to the number of trained features. The Data parameter provides data to the function. The data can be of different types. For NEURAL_LEARN/NEURAL_PREDICT it's a pointer to a double array of length NumSignals+1, containing the signal values plus the prediction objective or trade result at the end. Note that a plain data array has no "dim names" or other R gimmicks - if they are needed in the R training or predicting function, add them there. For NEURAL_TRAIN the Data parameter is a text string containing all samples in CSV format. The string can be stored in a temporary CSV file and then read by the machine learning algorithm for training the model. For NEURAL_SAVE/NEURAL_LOAD the Data parameter is the suggested file name for saving or loading all trained models of the current WFO cycle in the Data folder. Use the slash(string) function for converting backslashes to slashes when required for R file paths. The code below is the default neural function in the r.h file for using an R machine learning algorithm. A 64-bit variant for Python can be found in pynet.cpp. If required for special purposes, the default neural function can be replaced by a user-supplied function. var neural(int Status, int model, int NumSignals, void* Data) The default neural function requires an R script with the same name as the strategy script, but extension .r instead of .c. There is also a Python version available. The R or Python script must contain the following functions: neural.init() initializes the machine learning package, defines a model list, sets the initial seed, number of cores, GPU/CPU context, etc. neural.train(Model, XY) trains the algorithm and stores the trained model in the model list. XY is a data frame with signals in the first NumSignals columns and the objective in the last (NumSignals+1) column. The samples are the rows of the data frame. Model is the number in the model list where the trained model is to be stored. The model can be any R object combined from the machine learning model and any additional data, e.g., a set of normalization factors. In the Python version, XY is the file name of a .csv file with the data. neural.save(FileName) stores all models from the model list to a file with the given name and path. This function is called once per WFO cycle, so any cycle generates a file of all models of this cycle. neural.load(FileName) loads back the previously stored model list for the current WFO cycle. If this optional function is missing, the model list is loaded with the R load() function. Otherwise, make sure to load the list into the global R environment so that it is accessible to neural.predict, e.g., with load(FileName, envir=.GlobalEnv). neural.predict(Model, X) predicts the objective from the signals. X is a vector of size NumSignals, containing the signal values for a single prediction. Model is the number of the model in the model list. The neural.predict return value is returned by the advise function. The neural.predict function could also support batch predictions where X is a data frame with several samples and a vector Y is returned. Batch predictions are not used by Zorro, but useful for calibrating the algorithm with a training/test data set generated in SIGNALS mode. An example of such a deep learning system can be found on Financial Hacker. A simple machine learning strategy DeepLearn.c is included, together with R scripts for running it with the Deepnet, H2O, MxNet, or Keras deep learning packages. A .cpp version is available for PyTorch. The neural function is compatible with all Zorro trading, test, and training methods, including walk forward analysis, multi-core parallel training, and multiple assets and algorithms. A short description of installation and usage of popular deep learning packages can be found here. Remarks:
See also:optimize, frechet, polyfit, predict, Workshop 7, R Bridge, deep learning ► latest version online |
Machine LearningZorro kann integrierte oder externe Machine-Learning-Algorithmen nutzen, zum Beispiel aus R-Paketen, um 'künstliche Intelligenz' auf algorithmisches Trading anzuwenden. Drei interne Algorithmen zur Preisprognose sind verfügbar: ein Entscheidungsbaum, ein einfaches neuronales Netzwerk und ein Signal-Muster-Lernsystem. Sie generieren Handelsregeln separat für jeden WFO-Zyklus, Asset, Algo und Long- oder Short-Trades. Sie können auch Ihre eigene Funktion zum Trainieren eines individuellen Modells bereitstellen oder Funktionen aus R- oder Python-Paketen verwenden. Eine Einführung in verschiedene Machine-Learning-Methoden finden Sie auf Financial Hacker. Die advise-Funktionen werden verwendet, um einen Machine-Learning-Algorithmus genauso wie einen Standardindikator zu implementieren: adviseLong (int Method, var Objective, var Signal0, var Signal1, var Signal2, ..., var Signal19): varadviseShort (int Method, var Objective, var Signal0, var Signal1, var Signal2, ... var Signal19): varadviseLong (int Method, var Objective, var* Signals, int NumSignals): varadviseShort (int Method, var Objective, var* Signals, int NumSignals): varRufen Sie einen Machine-Learning-Algorithmus zum Trainieren oder zur Vorhersage auf. Im [Train]-Modus trainiert die Funktion den Algorithmus, um entweder einen nachfolgenden Trade-Rendite oder ein Trainingsziel (Objective) vorherzusagen. Im [Test] oder [Trade]-Modus ruft die Funktion den Algorithmus auf und gibt den vorhergesagten Wert zurück. Abhängig vom Algorithmus kann das Training ein binäres Modell oder eine Vorhersagefunktion im C-Code generieren, die im Data-Ordner gespeichert wird. Der einzige Unterschied der ..Long und ..Short Varianten besteht darin, dass sie auf die Renditen von Long- und Short-Trades trainieren können; ansonsten sind sie identisch. Sie können somit alternativ verwendet werden, um zwei verschiedene Modelle pro Algo/Asset-Komponente zu generieren. Parameter:
Rückgaben:
[Train]-Modus: 100, wenn Trade-Ergebnisse trainiert werden sollen, d.h. das RETURNS-Flag gesetzt ist oder Ziel null ist. Andernfalls 0. DTREE (Entscheidungsbaum)Ein Entscheidungsbaum ist ein baumartiges Entscheidungsdiagramm, bei dem Signale mit festen Werten verglichen werden. Die Werte und die Baumstruktur werden im Trainingslauf generiert. Dabei durchläuft der Trainingsprozess die Signalsets und findet die Signalwerte mit der niedrigsten Informationsentropie. Diese Werte werden dann verwendet, um den Datenraum in einen profitablen und einen nicht profitablen Teil zu spalten, dann wird der Prozess mit der Iteration durch die Teile fortgesetzt. Details zum Entscheidungsbaum-Algorithmus finden Sie in Büchern über Machine Learning. Die Signale sollten grob auf den Bereich -100..100 normalisiert werden, um die beste Präzision zu erzielen. Sie sollten sorgfältig ausgewählt werden, sodass die angezeigte Vorhersagegenauigkeit in allen WFO-Zyklen deutlich über 60% liegt. Entscheidungsbäume funktionieren am besten mit Signalen, die unabhängig voneinander sind. Sie funktionieren nicht sehr gut, wenn die Vorhersage von einer linearen Kombination der Signale abhängt. Um Overfitting zu reduzieren, werden die resultierenden Bäume beschnitten, indem unvorhersagende Signale entfernt werden. Die Ausgabe des Baumes ist eine Zahl zwischen -100 .. +100, abhängig von der Vorhersagequalität der aktuellen Signalkombination. Die Entscheidungsbaum-Funktionen werden im C-Quellcode in der \Data\*.c-Datei gespeichert. Die Funktionen werden automatisch in das Strategieskript eingebunden und von der advise-Funktion im Test- und Trade-Modus verwendet. Sie können auch exportiert werden, um sie in Strategieskripten oder Expert Advisors anderer Plattformen zu verwenden. Das untenstehende Beispiel ist ein typischer von Zorro generierter Entscheidungsbaum: int EURUSD_S(var* sig) Der advise()-Aufruf verwendete 5 Signale, von denen das erste und das letzte - sig[0] und sig[4] - keine Vorhersagekraft hatten und daher beschnitten wurden und nicht im Baum erscheinen. Unvorhersagende Signale werden im Nachrichtenfenster angezeigt. Beispiel für ein Skript zur Generierung eines Entscheidungsbaums: void run() { BarPeriod = 60; LookBack = 150; TradesPerBar = 2; if(Train) Hedge = 2; set(RULES|TESTNOW); // generiere Preisreihen vars H = series(priceHigh()), L = series(priceLow()), C = series(priceClose()); // generiere einige Signale aus H, L, C im Bereich -100..100 var Signals[2]; Signals[0] = (LowPass(H,1000)-LowPass(L,1000))/PIP; Signals[1] = 100*FisherN(C,100); // trainiere und handle die Signale Stop = 4*ATR(100); TakeProfit = 4*ATR(100); if(adviseLong(DTREE,0,Signals,2) > 0) enterLong(); if(adviseShort(DTREE,0,Signals,2) > 0) enterShort(); } PERCEPTRONEin Perzeptron, auch als logistische Regression Funktion bezeichnet, ist ein einfaches neuronales Netzwerk, bestehend aus einem Neuron mit einem Ausgang und bis zu 20 Signaleingängen. Es berechnet seine Vorhersagen aus einer linearen Kombination gewichteter Signale. Es weist einige Ähnlichkeiten mit dem polyfit-Algorithmus auf, jedoch mit beliebigen Variablen anstelle von Potenzen einer einzigen Variable und mit einem binären Ausgang. Eine kurze Beschreibung des Perzeptron-Algorithmus finden Sie auf der Machine Learning Übersicht. Die Signalgewichte werden im Trainingslauf generiert, um die bestmögliche Vorhersage zu erzielen. Die Signale sollten sich im einstelligen Bereich befinden, wie -1...1. Der Perzeptron-Algorithmus funktioniert am besten, wenn die gewichtete Summe der Signale Vorhersagekraft hat. Er funktioniert nicht gut, wenn die Vorhersage eine nichtlineare Signalkombination erfordert, d.h., wenn Trades nicht durch eine gerade Ebene im Signalspeicher getrennt werden. Ein klassisches Beispiel für eine Funktion, die ein Perzeptron nicht emulieren kann, ist ein logisches XOR. Oft kann ein Perzeptron verwendet werden, wo ein Entscheidungsbaum scheitert, und umgekehrt. Der Perzeptron-Lernalgorithmus generiert Vorhersagefunktionen im C-Quellcode in der \Data\*.c-Datei. Die Funktionen werden automatisch in das Strategieskript eingebunden und von der advise-Funktion im Test- und Trade-Modus verwendet. Sie können auch exportiert werden, um sie in Strategieskripten oder Expert Advisors anderer Plattformen zu verwenden. Die Ausgabe ist >0 für eine positive oder <0 für eine negative Vorhersage. Die Ausgabemagnitude ist die mit der Vorhersage verbundene Wahrscheinlichkeit in Prozent, z.B. 70 für eine geschätzte Wahrscheinlichkeit von 70%. Eine generierte Perzeptron-Funktion mit 3 Signalen und binärem Ausgang sieht wie folgt aus: int EURUSD_S(var* sig) Im FUZZY-Modus ist die Ausgabemagnitude äquivalent zur Vorhersagekraft, was es ermöglicht, Signale unterhalb eines Schwellenwerts zu ignorieren. Der Skalierungsfaktor, 2.50 im untenstehenden Beispiel, wird so berechnet, dass der durchschnittliche Perzeptron-Rückgabewert des Trainingssatzes eine Magnitude von 50 hat. Beispiel für ein unscharfes Perzeptron: int EURUSD_S(var* sig) Signale, die keine vorhersagenden Marktinformationen enthalten, erhalten ein Gewicht von 0. PATTERN (Muster-Analysator)Der Muster-Analysator ist eine intelligente Version klassischer Kerzenmuster-Indikatoren. Er verwendet keine vordefinierten Muster, sondern lernt diese aus historischen Preisdaten. Er wird normalerweise mit bis zu 20 Open-, Close-, High- oder Low-Preisen einer Anzahl von Kerzen gefüttert. Er vergleicht jedes Signal mit jedem anderen Signal und verwendet die Vergleichsergebnisse – größer, kleiner oder gleich – zur Klassifizierung des Musters. Die Signale können mit den Methoden PATTERN+2 .. PATTERN+6 in Gruppen unterteilt werden. Sie teilen die Signale in bis zu sechs Mustergruppen und vergleichen nur Signale innerhalb derselben Gruppe. Dies ist nützlich, wenn zum Beispiel nur die ersten beiden Kerzen und die letzten beiden Kerzen eines 3-Kerzen-Musters miteinander verglichen werden sollen, aber nicht die erste Kerze mit der dritten Kerze. PATTERN+2 erfordert eine gerade Anzahl von Signalen, von denen die erste Hälfte zur ersten und die zweite Hälfte zur zweiten Gruppe gehört. PATTERN+3 erfordert ebenfalls eine durch 3 teilbare Anzahl von Signalen und so weiter. Mustergruppen können Signale gemeinsam nutzen – zum Beispiel können Open, High, Low und Close der mittleren Kerze sowohl in der ersten als auch in der zweiten Gruppe erscheinen – solange die Gesamtzahl der Signale 20 nicht überschreitet. Abgesehen von der Gruppierung trifft Zorro keine Annahmen über die Signale und ihre Beziehungen. Daher kann der Muster-Analysator auch für andere Signale als Kerzenpreise verwendet werden. Alle Signale innerhalb einer Mustergruppe sollten die gleiche Einheit haben, um vergleichbar zu sein, aber verschiedene Gruppen können unterschiedliche Einheiten haben. Für Kerzenmuster werden normalerweise die High-, Low- und Close-Preise der letzten 3 Bars für die Signale verwendet – der Open ist nicht notwendig, da er normalerweise mit dem Close der vorherigen Kerze identisch ist. Weitere Signale, wie der gleitende Durchschnitt des Preises, können zur Verbesserung der Vorhersage hinzugefügt werden (aber in den meisten Fällen nicht). Für einfache Muster mit wenigen Signalen kann der Muster-Analysator direkte Musterfindungsfunktionen im einfachen C-Quellcode in der \Data\*.c-Datei generieren. Diese Funktionen werden automatisch in das Strategieskript eingebunden und von der advise-Funktion im Test- und Trade-Modus verwendet. Sie können auch exportiert werden, um sie in anderen Plattformen zu verwenden. Sie finden alle Muster, die 4 oder mehr Male im Trainingsdatensatz aufgetreten sind und eine positive Gewinnerwartung hatten. Sie geben das Informationsverhältnis des Musters zurück – das Verhältnis des Gewinnmittels zur Standardabweichung – multipliziert mit 100. Je besser das Informationsverhältnis, desto vorhersagender ist das Muster. Eine typische Musterfindungsfunktion mit 12 Signalen sieht wie folgt aus: int EURUSD_S(float* sig) { if(sig[1]<sig[2] && eqF(sig[2]-sig[4]) && sig[4]<sig[0] && sig[0]<sig[5] && sig[5]<sig[3] && sig[10]<sig[11] && sig[11]<sig[7] && sig[7]<sig[8] && sig[8]<sig[9] && sig[9]<sig[6]) return 19; if(sig[4]<sig[1] && sig[1]<sig[2] && sig[2]<sig[5] && sig[5]<sig[3] && sig[3]<sig[0] && sig[7]<sig[8] && eqF(sig[8]-sig[10]) && sig[10]<sig[6] && sig[6]<sig[11] && sig[11]<sig[9]) return 170; if(sig[1]<sig[4] && eqF(sig[4]-sig[5]) && sig[5]<sig[2] && sig[2]<sig[3] && sig[3]<sig[0] && sig[10]<sig[7] && eqF(sig[7]-sig[8]) && sig[8]<sig[6] && sig[6]<sig[11] && sig[11]<sig[9]) return 74; if(sig[1]<sig[4] && sig[4]<sig[5] && sig[5]<sig[2] && sig[2]<sig[0] && sig[0]<sig[3] && sig[7]<sig[8] && eqF(sig[8]-sig[10]) && sig[10]<sig[11] && sig[11]<sig[9] && sig[9]<sig[6]) return 143; if(sig[1]<sig[2] && eqF(sig[2]-sig[4]) && sig[4]<sig[5] && sig[5]<sig[3] && sig[3]<sig[0] && sig[10]<sig[7] && sig[7]<sig[8] && sig[8]<sig[6] && sig[6]<sig[11] && sig[11]<sig[9]) return 168; .... return 0; } Die eqF-Funktion im obigen Code überprüft, ob zwei Signale gleich sind. Signale, die sich weniger als der FuzzyRange unterscheiden, werden als gleich betrachtet. Es gibt zwei zusätzliche spezielle Methoden für den Muster-Analysator. Die FUZZY-Methode generiert eine Musterfindungsfunktion, die auch Muster findet, die leicht von den profitablen Mustern im Trainingsdatensatz abweichen können. Sie gibt Mustern eine höhere Punktzahl, wenn sie 'besser passen'. Die Abweichung kann mit FuzzyRange eingestellt werden. Eine typische unscharfe Musterfindungsfunktion sieht wie folgt aus: int EURUSD_S(float* sig) { double result = 0.; result += belowF(sig[1],sig[4]) * belowF(sig[4],sig[2]) * belowF(sig[2],sig[5]) * belowF(sig[5],sig[3]) * belowF(sig[3],sig[0]) * equF(sig[10],sig[11]) * belowF(sig[11],sig[7]) * belowF(sig[7],sig[8]) * belowF(sig[8],sig[9]) * belowF(sig[9],sig[6]) * 19; result += belowF(sig[4],sig[5]) * belowF(sig[5],sig[1]) * belowF(sig[1],sig[2]) * belowF(sig[2],sig[3]) * belowF(sig[3],sig[0]) * belowF(sig[10],sig[7]) * belowF(sig[7],sig[11]) * belowF(sig[11],sig[8]) * belowF(sig[8],sig[9]) * belowF(sig[9],sig[6]) * 66; result += belowF(sig[4],sig[1]) * belowF(sig[1],sig[2]) * belowF(sig[2],sig[0]) * belowF(sig[0],sig[5]) * belowF(sig[5],sig[3]) * belowF(sig[10],sig[11]) * belowF(sig[11],sig[7]) * belowF(sig[7],sig[8]) * belowF(sig[8],sig[6]) * belowF(sig[6],sig[11]) * 30; result += belowF(sig[1],sig[4]) * belowF(sig[4],sig[2]) * belowF(sig[2],sig[5]) * belowF(sig[5],sig[3]) * belowF(sig[3],sig[0]) * belowF(sig[7],sig[10]) * belowF(sig[10],sig[11]) * belowF(sig[11],sig[8]) * belowF(sig[8],sig[6]) * belowF(sig[6],sig[9]) * 70; result += belowF(sig[4],sig[5]) * belowF(sig[5],sig[1]) * belowF(sig[1],sig[2]) * belowF(sig[2],sig[3]) * belowF(sig[3],sig[0]) * belowF(sig[7],sig[10]) * belowF(sig[10],sig[8]) * belowF(sig[8],sig[11]) * belowF(sig[11],sig[9]) * belowF(sig[9],sig[6]) * 108; ... return result; } Die belowF-Funktion wird auf der Fuzzy Logic-Seite beschrieben. Die FAST-Methode generiert keinen C-Code; stattdessen generiert sie eine Liste von Mustern, die mit alphanumerischen Namen klassifiziert werden. Um ein Muster zu finden, wird es klassifiziert und sein Name mit der Musterliste verglichen. Dies ist etwa 4-mal schneller als die Musterfindungsfunktion im C-Code und kann auch größere und komplexere Muster mit bis zu 20 Signalen verarbeiten. Dies kann einen bemerkenswerten Unterschied in der Backtest-Zeit machen oder wenn zusätzliche Parameter trainiert werden müssen. Eine Muster-Namensliste sieht wie folgt aus (die Zahlen hinter dem Namen sind die Informationsverhältnisse): /* Pattern list for EURUSD_S Die FAST-Methode kann nicht in Kombination mit FUZZY oder mit FuzzyRange verwendet werden. Aber die FAST sowie die FUZZY-Methode können mit Mustergruppen kombiniert werden (z.B. PATTERN+FAST+2). Die Findequote des Muster-Analysators kann mit zwei Variablen angepasst werden: MusterAnzahlDie minimale Anzahl von Vorkommnissen der gefundenen Muster in der analysierten Preisreihe; Standardwert = 4. MusterRateDie minimale Gewinnrate der gefundenen Muster, in Prozent; Standardwert = 50. Ein Beispiel für ein Musterhandels-Skript finden Sie in Workshop 7. NEURAL (Allgemeines Machine Learning)Die NEURAL-Methode verwendet eine externe Machine-Learning-Bibliothek, zum Beispiel eine Support Vector Machine, Random Forest oder ein Deep Learning neuronales Netzwerk zur Vorhersage des nächsten Preises oder der nächsten Trade-Rendite in einem Algo-Trading-System. Viele Machine-Learning-Bibliotheken sind in R-Paketen oder Python-Bibliotheken verfügbar; daher ruft die NEURAL-Methode oft R oder Python-Funktionen zum Trainieren und Vorhersagen auf. Aber jede DLL-basierte Machine-Learning-Bibliothek kann verwendet werden, solange die neural-Funktion – siehe unten – darauf angepasst ist. neural (int Status, int Model, int NumSignals, void* Data): varDiese Funktion wird automatisch mehrmals während des Trainings-, Test- oder Trade-Prozesses aufgerufen. Sie hat Zugriff auf alle globalen und vordefinierten Variablen. Ihr Verhalten hängt von Status ab:
Model ist die Nummer des trainierten Modells, zum Beispiel eine Reihe von Entscheidungsregeln oder eine Reihe von Gewichten eines neuronalen Netzwerks, beginnend mit 0. Wenn mehrere Modelle für Long- und Short-Vorhersagen und für verschiedene Assets oder Algos trainiert werden, wählt der Index das geeignete Modell aus. Die Anzahl der Modelle ist daher normalerweise gleich der Anzahl der advise-Aufrufe pro run-Zyklus. Alle trainierten Modelle werden am Ende jedes WFO-Zyklus in einer *.ml-Datei gespeichert. In R werden die Modelle normalerweise in einer Liste von Listen gespeichert und über ihren Index (z.B. Models[[model+1]]) zugegriffen. Jeder zusätzliche Parametersatz, der im Trainingsprozess generiert wird – zum Beispiel eine Reihe von Normalisierungsfaktoren oder Auswahlmasken für die Signale – kann als Teil des Modells gespeichert werden. Der NumSignals-Parameter ist die Anzahl der Signale, die an die advise-Funktion übergeben werden. Er ist normalerweise identisch mit der Anzahl der trainierten Merkmale. Der Data-Parameter liefert Daten an die Funktion. Die Daten können verschiedener Typen sein. Für NEURAL_LEARN/NEURAL_PREDICT ist es ein Zeiger auf ein double-Array der Länge NumSignals+1, das die Signalwerte plus das Vorhersageziel oder das Trade-Ergebnis am Ende enthält. Beachten Sie, dass ein einfaches Datenarray keine "dim names" oder andere R-Kleinigkeiten hat – wenn diese im R-Trainings- oder Vorhersagefunktion benötigt werden, fügen Sie sie dort hinzu. Für NEURAL_TRAIN ist der Data-Parameter ein Textstring, der alle Samples im CSV-Format enthält. Der String kann in einer temporären CSV-Datei gespeichert und dann von dem Machine-Learning-Algorithmus zum Trainieren des Modells gelesen werden. Für NEURAL_SAVE/NEURAL_LOAD ist der Data-Parameter der vorgeschlagene Dateiname zum Speichern oder Laden aller trainierten Modelle des aktuellen WFO-Zyklus im Data-Ordner. Verwenden Sie die slash(string)-Funktion, um Backslashes in Slashes umzuwandeln, wenn dies für R-Dateipfade erforderlich ist. Der untenstehende Code ist die Standard-neural-Funktion in der r.h-Datei zur Verwendung eines R-Machine-Learning-Algorithmus. Eine 64-Bit-Variante für Python ist in pynet.cpp verfügbar. Wenn erforderlich für spezielle Zwecke, kann die Standard-neural-Funktion durch eine benutzerdefinierte Funktion ersetzt werden. var neural(int Status, int model, int NumSignals, void* Data) Die Standard-neural-Funktion erfordert ein R-Skript mit demselben Namen wie das Strategieskript, aber der Erweiterung .r statt .c. Es gibt auch eine Python-Version. Das R- oder Python-Skript muss die folgenden Funktionen enthalten: neural.init() initialisiert das Machine-Learning-Paket, definiert eine Modellliste, setzt den initialen Seed, die Anzahl der Kerne, GPU/CPU-Kontext usw. neural.train(Model, XY) trainiert den Algorithmus und speichert das trainierte Modell in der Modellliste. XY ist ein Data Frame mit Signalen in den ersten NumSignals Spalten und dem Ziel in der letzten (NumSignals+1) Spalte. Die Samples sind die Zeilen des Data Frames. Model ist die Nummer in der Modellliste, in der das trainierte Modell gespeichert werden soll. Das Modell kann jedes R-Objekt sein, das aus dem Machine-Learning-Modell und zusätzlichen Daten zusammengesetzt ist, z.B. eine Reihe von Normalisierungsfaktoren. In der Python-Version ist XY der Dateiname einer .csv-Datei mit den Daten. neural.save(FileName) speichert alle Modelle aus der Modellliste in einer Datei mit dem angegebenen Namen und Pfad. Diese Funktion wird einmal pro WFO-Zyklus aufgerufen, sodass jeder Zyklus eine Datei aller Modelle dieses Zyklus generiert. neural.load(FileName) lädt die zuvor gespeicherte Modellliste für den aktuellen WFO-Zyklus zurück. Wenn diese optionale Funktion fehlt, wird die Modellliste mit der R-Funktion load() geladen. Andernfalls stellen Sie sicher, dass die Liste in die globale R-Umgebung geladen wird, damit sie für neural.predict zugänglich ist, z.B. mit load(FileName, envir=.GlobalEnv). neural.predict(Model, X) sagt das Ziel basierend auf den Signalen voraus. X ist ein Vektor der Größe NumSignals, der die Signalwerte für eine einzelne Vorhersage enthält. Model ist die Nummer des Modells in der Modellliste. Der Rückgabewert der neural.predict-Funktion wird von der advise-Funktion zurückgegeben. Die neural.predict-Funktion könnte auch Batch-Vorhersagen unterstützen, bei denen X ein Data Frame mit mehreren Samples ist und ein Vektor Y zurückgegeben wird. Batch-Vorhersagen werden von Zorro nicht verwendet, sind aber nützlich, um den Algorithmus mit einem Trainings/Test-Datensatz zu kalibrieren, der im SIGNALS-Modus generiert wurde. Ein Beispiel für ein solches Deep-Learning-System finden Sie auf Financial Hacker. Eine einfache Machine-Learning-Strategie DeepLearn.c ist enthalten, zusammen mit R-Skripten zur Ausführung mit den Deep-Learning-Paketen Deepnet, H2O, MxNet oder Keras. Eine .cpp-Version ist für PyTorch verfügbar. Die neural-Funktion ist mit allen Zorro-Trading-, Test- und Trainingsmethoden kompatibel, einschließlich Walk Forward Analysis, Multi-Core-Parallelen Training und mehreren Assets und Algorithmen. Eine kurze Beschreibung der Installation und Verwendung beliebter Deep-Learning-Pakete finden Sie hier. Anmerkungen:
Siehe auch:optimize, frechet, polyfit, predict, Workshop 7, R Bridge, deep learning ► Neueste Version online |