Bei der Erstellung einer quantitativen Handelsstrategie mit den K-Liniendaten gibt es oft Fälle, in denen nicht-standardmäßige Zyklus-K-Liniendaten erforderlich sind. Zum Beispiel sind 12-minütige Zyklus-K-Liniendaten und 4-stündige K-Linienzyklus-Daten erforderlich. Normalerweise sind solche nicht-standardmäßigen Zyklen nicht direkt verfügbar. Wie befassen wir uns mit solchen Bedürfnissen?
Die Daten der nicht standardisierten Zyklus-K-Linie können durch die Kombination der Daten des kleineren Zyklus erhalten werden. Hierbei wird der höchste Preis in mehreren Zyklen als der höchste Preis nach der Synthese der mehreren Zyklus-K-Linie gezählt, und der niedrigste Preis wird als der niedrigste Preis nach der Synthese berechnet, und der Eröffnungspreis ändert sich nicht. Der erste Eröffnungspreis der Rohstoffdaten der K-Linie wird synthetisiert. Der Schlusskurs entspricht dem Schlusskurs der letzten Rohstoffdaten der K-Linie. Die Zeit verwendet die Zeit der Eröffnungspreislinie k. Das Transaktionsvolumen verwendet die Rohstoffdaten, die summiert und berechnet wurden.
Wie in der Abbildung gezeigt:
Nehmen wir das Blockchain-Asset BTC_USDT als Beispiel und synthetisieren wir 1 Stunde in 4 Stunden.
Zeit | Höchste | Geöffnet | Niedrigste | Schließen |
---|---|---|---|---|
2019.8.12 00:00 | 11447.07 | 11382.57 | 11367.2 | 11406.92 |
2019.8.12 01:00 | 11420 | 11405.65 | 11366.6 | 11373.83 |
2019.8.12 02:00 | 11419.24 | 11374.68 | 11365.51 | 11398.19 |
2019.8.12 03:00 | 11407.88 | 11398.59 | 11369.7 | 11384.71 |
Die Daten von vier 1-Stunden-Zyklen werden zu einer einzigen 4-Stunden-Zyklusdaten zusammengefasst.
Der Eröffnungspreis ist der Eröffnungspreis der ersten K-Linie um 00:00 Uhr: 11382.57 Der Schlusskurs ist der Schlusskurs der letzten K-Linie um 03:00 Uhr: 11384.71 Der höchste Preis ist der höchste Preis unter ihnen zu finden: 11447,07 Der niedrigste Preis ist der niedrigste Preis unter ihnen zu finden: 11365,51
Anmerkung: China Commodity Futures Market schließt an einem normalen Handelstag um 15:00 Uhr
Die 4-Stunden-Zyklusstartzeit ist die Startzeit der ersten 1-stündigen K-Linie, d. h. 2019.8.12 00:00
Die Summe des Volumens aller 1-Stunden-K-Linien wird als dieses 4-Stunden-K-Linienvolumen verwendet.
Eine 4-stündige K-Linie wird synthetisiert:
High: 11447.07
Open: 11382.57
Low: 11365.51
Close: 11384.71
Time: 209.8.12 00:00
Sie können sehen, dass die Daten konsistent sind.
Nachdem Sie die ersten Ideen verstanden haben, können Sie den Code manuell schreiben, um die Anforderungen zu erfüllen.
Diese Codes dienen nur als Referenz:
function GetNewCycleRecords (sourceRecords, targetCycle) { // K line synthesis function
var ret = []
// First get the source K line data cycle
if (!sourceRecords || sourceRecords.length < 2) {
Return null
}
var sourceLen = sourceRecords.length
var sourceCycle = sourceRecords[sourceLen - 1].Time - sourceRecords[sourceLen - 2].Time
if (targetCycle % sourceCycle != 0) {
Log("targetCycle:", targetCycle)
Log("sourceCycle:", sourceCycle)
throw "targetCycle is not an integral multiple of sourceCycle."
}
if ((1000 * 60 * 60) % targetCycle != 0 && (1000 * 60 * 60 * 24) % targetCycle != 0) {
Log("targetCycle:", targetCycle)
Log("sourceCycle:", sourceCycle)
Log((1000 * 60 * 60) % targetCycle, (1000 * 60 * 60 * 24) % targetCycle)
throw "targetCycle cannot complete the cycle."
}
var multiple = targetCycle / sourceCycle
var isBegin = false
var count = 0
var high = 0
var low = 0
var open = 0
var close = 0
var time = 0
var vol = 0
for (var i = 0 ; i < sourceLen ; i++) {
// Get the time zone offset value
var d = new Date()
var n = d.getTimezoneOffset()
if ((1000 * 60 * 60 * 24) - sourceRecords[i].Time % (1000 * 60 * 60 * 24) + (n * 1000 * 60)) % targetCycle == 0) {
isBegin = true
}
if (isBegin) {
if (count == 0) {
High = sourceRecords[i].High
Low = sourceRecords[i].Low
Open = sourceRecords[i].Open
Close = sourceRecords[i].Close
Time = sourceRecords[i].Time
Vol = sourceRecords[i].Volume
count++
} else if (count < multiple) {
High = Math.max(high, sourceRecords[i].High)
Low = Math.min(low, sourceRecords[i].Low)
Close = sourceRecords[i].Close
Vol += sourceRecords[i].Volume
count++
}
if (count == multiple || i == sourceLen - 1) {
Ret.push({
High : high,
Low : low,
Open : open,
Close : close,
Time : time,
Volume : vol,
})
count = 0
}
}
}
Return ret
}
// test
function main () {
while (true) {
var r = exchange.GetRecords() // Raw data, as the basic K-line data of the synthesize K line. for example, to synthesize a 4-hour K-line, you can use the 1-hour K-line as the raw data.
var r2 = GetNewCycleRecords(r, 1000 * 60 * 60 * 4) // Pass the original K-line data r through the GetNewCycleRecords function, and the target cycles, 1000 * 60 * 60 * 4, ie the target synthesis cycle is 4 hours K-line data .
$.PlotRecords(r2, "r2") // The strategy class library bar can be selected by check the line class library, and calling the $.PlotRecords line drawing class library to export the function drawing.
Sleep(1000) // Each cycle is separated by 1000 milliseconds, preventing access to the K-line interface too much, resulting in transaction restrictions.
}
}
Um die K-Linie zu synthetisieren, braucht man zwei Dinge. Das erste sind die Rohstoffdaten, also die K-Linie-Daten eines kleineren Zyklus.var r = exchange.GetRecords()
Um die kleineren Daten der Zyklus-K-Linie zu erhalten.
Die zweite ist, um die Größe des Synthese-Zyklus zu ermitteln, verwenden wir den GetNewCycleRecords-Funktionsalgorithmus, um dies zu tun, dann können Sie endlich die Daten einer synthetisierten K-Linien-Array-Struktur zurückgeben.
Bitte beachten Sie:
Der Zielzyklus kann nicht kleiner sein als der Zyklus der K-Linie, die Sie in der Funktion GetNewCycleRecords als Rohstoff für die Daten übergeben haben.
Der Zielzyklus muss auf
Zum Beispiel:
Die K-Linie des 12-minütigen Zyklus beginnt jede Stunde von 0:0, der erste Zyklus ist 00:00:00 ~ 00:12:00, und der zweite Zyklus ist 00:12: 00 ~ 00: 24:00, der dritte Zyklus ist 00:24:00 ~ 00:36:00, der vierte Zyklus ist 00:36:00 ~ 00:48:00, der fünfte Zyklus ist 00:48 :00 ~ 01:00:00, die genau eine vollendete Stunde sind.
Wenn es sich um einen Zyklus von 13 Minuten handelt, handelt es sich um einen Zyklus, der nicht geschlossen ist. Die durch einen solchen Zyklus berechneten Daten sind nicht einzigartig, da sich die synthetisierten Daten je nach Ausgangspunkt der synthetisierten Daten unterscheiden.
Führe es auf den echten Markt:
Kontrastwechselkarte
Ich möchte den gleitenden Durchschnitt des höchsten Preises für alle K-Linien berechnen.
Normalerweise berechnen wir die gleitenden Durchschnitte mit dem Durchschnitt der Schlusskurs, aber manchmal gibt es Nachfrage, um den höchsten Preis, den niedrigsten Preis, den Eröffnungspreis und so weiter zu verwenden.
für diese zusätzlichen Anforderungen können die von der Exchange.GetRecords() Funktion zurückgegebenen K-Zeilendaten nicht direkt an die Indikatorberechnungsfunktion übergeben werden.
Zum Beispiel:
Dietalib.MA
Die Funktion zur Berechnung des gleitenden Durchschnittsindikators hat zwei Parameter, der erste ist die Daten, die eingegeben werden müssen, und der zweite ist der Indikatorzyklusparameter.
Wir müssen beispielsweise die Indikatoren wie unten dargestellt berechnen.
Der K-Linienzyklus dauert 4 Stunden.
Auf dem Kursdiagramm wurde eine Durchschnittslinie mit dem Zyklusparameter 9 festgelegt.
Die berechnete Datenquelle verwendet den höchsten Preis pro Bar.
Das heißt, diese gleitende Durchschnittslinie besteht aus dem Durchschnitt des höchsten Durchschnittspreises von neun 4-Stunden-Zyklus K-Line Bar.
Lassen Sie uns selbst eine Datenbank erstellen, um zu sehen, ob sie mit den Daten der Börse identisch ist.
var highs = []
for (var i = 0 ; i < r2.length ; i++) {
highs.push(r2[i].High)
}
Da wir den höchsten Preis für jeden Bar berechnen müssen, um den Wert des gleitenden Durchschnittsindikators zu erhalten, müssen wir ein Array erstellen, in dem jedes Datenelement den höchsten Preis für jeden Bar hat.
Sie können sehen, dass diehighs
Die Variable ist zunächst ein leeres Array, dann durchqueren wir die Datenvariable r2 k-Linien (erinnern Sie sich nicht an die r2? Schauen Sie sich den Code in der Hauptfunktion an, der die 4-Stunden-K-Linie oben synthetisiert).
Lesen Sie den höchsten Preis von jedem Bar von r2 (d. h. r2[i].High, i reicht von 0 bis r2.länge - 1), dann drücken Sie inhighs
Auf diese Weise konstruieren wir einfach eine Datenstruktur, die eins zu eins mit der K-Linien-Datenleiste korrespondiert.
In diesem Moment,highs
kann dietalib.MA
Funktion zur Berechnung des gleitenden Durchschnitts.
Vollständiges Beispiel:
function main () {
while (true) {
var r = exchange.GetRecords()
var r2 = GetNewCycleRecords(r, 1000 * 60 * 60 * 4)
if (!r2) {
Continue
}
$.PlotRecords(r2, "r2") // Draw the K line
var highs = []
for (var i = 0 ; i < r2.length ; i++) {
Highs.push(r2[i].High)
}
var ma = talib.MA(highs, 9) // use the moving average function "talib.MA" to calculate the moving average indicator
$.PlotLine("high_MA9", ma[ma.length - 2], r2[r2.length - 2].Time) // Use the line drawing library to draw the moving average indicator on the chart
Sleep(1000)
}
}
Rücktest:
Sie können sehen, dass der durchschnittliche Indikatorwert der Mauspunktposition in der Abbildung ist 11466.9289
Der obige Code kann in die Strategie kopiert werden, um den Test auszuführen, denken Sie daran, die
Die FMZ Quant-Plattform verfügt bereits über eine verpackte Schnittstelle, nämlich die
exchange.GetRecords
Funktion, um K-Liniendaten zu erhalten.
Das Folgende konzentriert sich auf den direkten Zugriff auf den AustauschGetRecords
Wenn Sie auf eine Strategie stoßen, die zunächst mehr als 100 K-Zeilen erfordert, müssen Sie auf den Sammelvorgang warten.
Um die Strategie so schnell wie möglich funktionieren zu lassen, können Sie eine Funktion einkapseln, direkt auf die K-Linie-Schnittstelle der Börse zugreifen und Parameter angeben, um mehr K-Linie-Daten zu erhalten.
Mit dem BTC_USDT-Handelspaar auf der Huobi-Börse als Beispiel implementieren wir diese Anforderung:
Finden Sie die API-Dokumentation der Exchange
https://huobiapi.github.io/docs/spot/v1/en/#get-klines-candles
Parameter:
Name | Typ | Ist das notwendig? | Beschreibung | Wert |
---|---|---|---|---|
Symbol | String | - Das stimmt. | Handelspaar | Ich will nicht, dass du mich verarschst. |
Periode | String | - Das stimmt. | Gibt die zeitliche Granularität der Daten zurück, d. h. das Zeitintervall jeder k-Zeile | 1 Minute, 5 Minuten, 15 Minuten, 30 Minuten, 60 Minuten, 1 Tag, 1 Monat, 1 Woche, 1 Jahr |
Größe | ganzzahl | falsche | Gibt die Anzahl der Datenzeilen zurück | [1, 2000] |
Prüfcode:
function GetRecords_Huobi (period, size, symbol) {
var url = "https://api.huobi.pro/market/history/kline?" + "period=" + period + "&size=" + size + "&symbol=" + symbol
var ret = HttpQuery(url)
try {
var jsonData = JSON.parse(ret)
var records = []
for (var i = jsonData.data.length - 1; i >= 0 ; i--) {
records.push({
Time : jsonData.data[i].id * 1000,
High : jsonData.data[i].high,
Open : jsonData.data[i].open,
Low : jsonData.data[i].low,
Close : jsonData.data[i].close,
Volume : jsonData.data[i].vol,
})
}
return records
} catch (e) {
Log(e)
}
}
function main() {
var records = GetRecords_Huobi("1day", "300", "btcusdt")
Log(records.length)
$.PlotRecords(records, "K")
}
Sie können das auf dem Protokoll sehen, Druckrecords.length
ist 300, d. h. die Anzahl derrecords
Die Datenleiste ist 300.