Die Ressourcen sind geladen. Beförderung...

Ich lehre Sie Strategien zu schreiben - eine MyLanguage-Strategie transplantieren (Advanced)

Schriftsteller:FMZ~Lydia, Erstellt: 2022-12-26 18:56:00, Aktualisiert: 2023-09-20 09:46:34

img

Sie lernen Strategien zu schreiben eine MyLanguage-Strategie zu transplantieren (Advanced)

Im letzten ArtikelSie lernen, Strategien zu schreiben -- transplantieren Sie eine MyLanguage-Strategie, eine einfache MyLanguage-Strategie wurde für die Transplantation getestet. Wenn es sich um eine komplexere MyLanguage handelt, wie kann sie in eine JavaScript-Sprachstrategie transplantiert werden? Welche Fähigkeiten gibt es?

Schauen wir uns zunächst die zu transplantierende Strategie an:

(*backtest
start: 2019-05-01 00:00:00
end: 2019-11-12 00:00:00
period: 1d
exchanges: [{"eid":"Futures_OKCoin","currency":"BTC_USD"}]
args: [["SlideTick",10,126961],["ContractType","quarter",126961]]
*)

N1:=10;
N2:=21;
AP:=(HIGH+LOW+CLOSE)/3;
ESA:=EMA(AP,N1);
D:=EMA(ABS(AP-ESA),N1);
CI:=(AP-ESA)/(0.015*D);
TCI:=EMA(CI,N2);
WT1:TCI;
WT2:SMA(WT1,4,1);
AA:=CROSS(WT1,WT2);
BB:=CROSSDOWN(WT1,WT2);
REF(AA,1),BPK;
REF(BB,1),SPK;

Die(* backtest... *)zu Beginn der MyLanguage-Strategie ist der Konfigurationscode für Backtesting-Einstellungen. Um den Vergleich zu erleichtern, wird eine einheitliche Backtesting-Konfiguration festgelegt. Diese Strategie ist auch eine zufällige, die nicht zu komplex ist (komplexer als in dem letzten Artikel). Es ist eine repräsentative Strategie. Um eine MyLanguage-Strategie zu transplantieren, sollten Sie sich zuerst die gesamte Strategie ansehen. Der Code der Strategie ist prägnant und Sie können ein gewisses Verständnis der Gesamtstrategie haben. Für diese Strategie haben wir gesehen, dass mehrere IndikatorfunktionenEMA, SMAverwendet wurden:

Bauen Sie zuerst ein Rad.

  • Die EMA Die Indikator-Funktion, es gibt fertige Indikator-Bibliothek-Funktionen, die direkt in der FMZ-Plattform verfügbar sind, wenn Strategien in JavaScript geschrieben werden. Das heißt:TA.MA.

  • SMA Was wir tun müssen, istSMADer Indikator, den wir in der TA-Bibliothek von FMZ gefunden haben, unterstützt nicht die SMA-Indikatorfunktion, und es gibt Unterschiede zwischen dem SMA-Indikator in der Talib-Bibliothek und dem in MyLanguage.

img

Wie wir sehen können, hat der Parameterbereich einen Gewichtsparameter zusätzlich zum Periodenparameter.

Die SMA-Indikatorfunktion in der Talib-Bibliothek in der FMZ-API-Dokumentation wird wie folgt beschrieben:

img

Es ist zu sehen, daßtalib.SMAist ein einfacher gleitender Durchschnittsindikator. Auf diese Weise können wir eine SMA nur selbst implementieren. Als Entwickler, der die JavsScript-Sprache verwendet, um Strategien zu schreiben, ist dies auch eine der notwendigen Fähigkeiten. Immerhin, wenn es kein fertiges Rad gibt, muss das Programm immer noch ausgeführt werden, einfach eins bauen.

Es gibt nicht viel Forschung über Indikatoren usw. Im Allgemeinen suchen die Menschen nach Informationen, wenn sie sie nicht verstehen.

img

Es scheint, dass der Algorithmusprozess dieser Theorie ziemlich zuverlässig ist, und die Implementierung ist wie folgt:

function SMA (arr, n, m) {
    var sma = []
    var currSMA = null
    for (var i = 0; i < arr.length; i++) {
        if (arr[i] && !isNaN(arr[i])) {
            if (!currSMA) {
                currSMA = arr[i]
                sma.push(currSMA)
                continue
            }  

            // [M*C2+(N-M)*S1]/N
            currSMA = (m * arr[i] + (n - m) * currSMA) / n
            sma.push(currSMA)
        } else {
            sma.push(NaN)
        }
    }  

    return sma
}

Schreiben von ausgefüllten Abschnitten

Der Strategie-Rahmen verwendet denselben Rahmen wie der in ArtikelSie lernen, Strategien zu schreiben -- transplantieren Sie eine MyLanguage-Strategieund hauptsächlich in zwei Teilen gefüllt:

Zuerst machen Sie Tickerdatenverarbeitung und Indexberechnung.

img

Nehmen wir diesen Teil der MyLanguage Satz für Satz, Funktion für Funktion:

    1. AP:=(HIGH+LOW+CLOSE)/3;

Es kann verstanden werden, dass der höchste Preis, der niedrigste Preis und der Schlusskurs jedes BAR in den Daten der Zeile K addiert und dann durch 3 dividiert werden, um den Durchschnittswert zu berechnen, und dann als Matrix gespeichert werden, die jedem BAR einzeln entspricht. Sie kann wie folgt verarbeitet werden:

function CalcAP (r) {   // AP:=(HIGH+LOW+CLOSE)/3;
    var arrAP = []      // Declare an empty array

    for (var i = 0; i < r.length; i++) {      // r is the incoming K-line data, which is an array, use for to traverse this array.
        v = (r[i].High + r[i].Low + r[i].Close) / 3      // Calculate the average value.
        arrAP.push(v)                                    // Add to the end of the arrAP array, the end is the first when arrAP is empty.
    }  

    return arrAP     // Returns this average array, i.e., the AP calculated in the MyLanguage 
}

Diese Funktion kann in der Hauptschleife OnTick-Funktion aufgerufen werden, zum Beispiel:

// Calculation of indicators
// AP
var ap = CalcAP(records)
    1. Nach Abschluss der AP-Berechnung wird mit der Berechnung fortgesetzt.ESA:=EMA(AP,N1);:

Hier werden wir die in dem vorherigen Schritt berechneten Daten von AP verwenden, um das ESA zu berechnen. Tatsächlich ist das ESA der exponentielle gleitende Durchschnitt des AP, also der EMA-Indikator. Wir werden AP als Daten und N1 als Parameter des EMA-Indikators verwenden, um den EMA-Indikator zu berechnen.

function CalcESA (ap, n1) {   // ESA:=EMA(AP,N1);
    if (ap.length <= n1) {    // If the AP length is less than the indicator parameter, valid data cannot be calculated. At this time, let the function return false.
        return false
    }  

    return TA.EMA(ap, n1)
}
    1. D:=EMA(ABS(AP-ESA),N1);

Verwenden Sie die berechnetenAP, ESAzur Berechnung der DatenD- Ich weiß. Die Kommentare zum Code finden Sie hier, um Tipps zur Berechnung der Indikatoren zu erhalten.

function CalcD (ap, esa, n1) {    // D:=EMA(ABS(AP-ESA),N1);
    var arrABS_APminusESA = []
    if (ap.length != esa.length) {
        throw "ap.length != esa.length"
    }  

    for (var i = 0; i < ap.length; i++) {
        // When calculating the value of the indicator, it is necessary to determine the validity of the data, because the first few EMA calculations may be the beginning of the array of data is NaN, or null.
        // So it must be judged that the data involved in the calculation are all valid values to proceed, and if there are any invalid values, they are filled with NaN to arrABS_APminusESA.
        // The data thus calculated, each position corresponds to the previous data one by one, without misalignment.
        if (ap[i] && esa[i] && !isNaN(ap[i]) && !isNaN(esa[i])) {
            v = Math.abs(ap[i] - esa[i])     // According to ABS(AP-ESA), the specific value is calculated and put into the arrABS_APminusESA array.
            arrABS_APminusESA.push(v)
        } else {
            arrABS_APminusESA.push(NaN)
        }
    }  

    if (arrABS_APminusESA.length <= n1) {
        return false
    }  

    return TA.EMA(arrABS_APminusESA, n1)    // Calculate the EMA indicator of the array arrABS_APminusESA and get the data D (array structure).
}
    1. CI:=(AP-ESA)/(0.015*D);Die Berechnungsmethode ist ähnlich wie in Schritt 1 und der Code wird direkt freigegeben.
function CalcCI (ap, esa, d) {    // CI:=(AP-ESA)/(0.015*D);
    var arrCI = []
    if (ap.length != esa.length || ap.length != d.length) {
        throw "ap.length != esa.length || ap.length != d.length"
    }
    for (var i = 0; i < ap.length; i++) {
        if (ap[i] && esa[i] && d[i] && !isNaN(ap[i]) && !isNaN(esa[i]) && !isNaN(d[i])) {
            v = (ap[i] - esa[i]) / (0.015 * d[i])
            arrCI.push(v)
        } else {
            arrCI.push(NaN)
        }
    }  

    if (arrCI.length == 0) {
        return false
    }  

    return arrCI
}
  • TCI:=EMACI,N2); Berechnen Sie einfach den EMA-Indikator für das CI-Array.
function CalcTCI (ci, n2) {   // TCI:=EMA(CI,N2);
    if (ci.length <= n2) {
        return false
    }  

    return TA.EMA(ci, n2)
}
  • WT2:SMA(WT1,4,1);

In diesem letzten Schritt wird die SMA-Funktion des vorher gebauten Rades verwendet.

function CalcWT2 (wt1) {    // WT2:SMA(WT1,4,1);
    if (wt1.length <= 4) {
        return false 
    }  

    return SMA(wt1, 4, 1)   // The SMA indicator for wt1 is calculated by using our own implementation of the SMA function.
}

Die Übertragung von Handelssignalen ist sehr einfach.

AA:=CROSS(WT1,WT2);
BB:=CROSSDOWN(WT1,WT2);
REF(AA,1),BPK;
REF(BB,1),SPK;

Nach dem Lesen dieser Codes von MyLanguage können wir sehen, dass das Goldene Kreuz und der bärische Crossover von WT1 und WT2 als Eröffnungsbedingungen verwendet werden. Mit dem direkten MyLanguage-Strategie-Backtest beobachten wir:

img

Aus der Beobachtung der tatsächlichen Funktionsweise der MyLanguage-Strategie geht hervor, dass, wenn ein Signal an der Eröffnungsposition erkannt wird, es tatsächlich darauf abzielt, zu erkennen, ob die Position des BAR an der Eröffnungsstelle mit 2 BARs nach vorne ein Goldenes Kreuz ist.

img img

Der Ausfüllcode des Signalerkennungsteils kann wie folgt geschrieben werden:

if ((_State == IDLE || _State == SHORT) && wt1[wt1.length - 4] < wt2[wt2.length - 4] && wt1[wt1.length - 3] > wt2[wt2.length - 3]) {
    if (_State == IDLE) {
        _State = OPENLONG
        Log("OPENLONG")    // test
    }
    if (_State == SHORT) {
        _State = COVERSHORT
        Log("COVERSHORT")  // test
    }
    isOK = false  
}

if ((_State == IDLE || _State == LONG) && wt1[wt1.length - 4] > wt2[wt2.length - 4] && wt1[wt1.length - 3] < wt2[wt2.length - 3]) {
    if (_State == IDLE) {
        _State = OPENSHORT
        Log("OPENSHORT")  // test
    }
    if (_State == LONG) {
        _State = COVERLONG
        Log("COVERLONG")  // test
    }
    isOK = false   
}

Hier können Sie darüber nachdenken, warum die SPK- und BPK-Anweisungen der MyLanguage mit dem obigen Code implementiert werden können.

Zurückprüfung

Backtestkonfiguration:

img

Backtest in MyLanguage:

img

Backtest in JavaScript Version:

img img

Der Code am Anfang der OnTick-Funktion wird verwendet, um das Backtesting zu beschleunigen. Er wird verwendet, um die Strategie basierend auf dem Bar-Modell auszuführen. Wenn Sie interessiert sind, können Sie sie detailliert analysieren.

function OnTick(){
    // The ticker processing part of the driving strategy.
    var records = _C(exchange.GetRecords)
    if (records[records.length - 1].Time == preTime) {
        if (isOK) {
            Sleep(500)
            return 
        }
    } else {
        preTime = records[records.length - 1].Time
    }
    ...
    ..
    .

Der vollständige Code der Lehrstrategie:https://www.fmz.com/strategy/174457

Danke fürs Lesen.


Mehr