[TOC]
Dieses Tutorial enthält grundlegende Kenntnisse des Schreibens von Strategien, einschließlich API-Einführung, Backtest, Diagramme und mehr. Nach dem Erlernen dieses grundlegenden Tutorials werden Benutzer in der Lage sein, die grundlegende API kompetent zu verwenden und eine stabile Bot-Strategie zu schreiben. Bevor Sie das Tutorial lernen, müssen Sie lernen, wie manStart der FMZ Quant-Plattform.
Alte Version Tutorial:FMZ Quant (FMZ.COM) Strategie Schreibhandbuch 2.0 (Tutorial); es gibt viele Post-Index im Tutorial, die empfohlen werden zu lesen.
Bei dem Programmhandel handelt es sich um die Nutzung von Programmen, um sich über eine API mit Plattformen zu verbinden, um automatische Kauf- und Verkaufsfunktionen oder andere Funktionen gemäß der Designabsicht zu erreichen.
Derzeit gibt es zwei Hauptschnittstellenprotokolle für Kryptowährungsplattformen: REST und Websocket. Jedes Mal, wenn das REST-Protokoll Daten erhält, muss es einmal zugegriffen werden. Nehmen wir die API der simulierten Plattform
{"data:{"buy":"11351.73","high":"11595.77","last":"11351.85","low":"11118.45","open":"11358.74","quoteVol":"95995607137.00903936","sell":"11356.02","time":1565593489318,"vol":"3552.5153"}}
Auf diese Weise können Sie sehen, dass sich der Handel nach den neuesten Marktnoten des Handelspaares BTC_USDT jedes Mal ändert, wenn es aktualisiert wird;
Die FMZ Quant-Handelsplattform umfasst die REST-Schnittstelle jeder Plattform und verwendet eine einheitliche Anrufart und ein einheitliches Datenformat, wodurch das Schreiben von Strategien einfacher und allgemeiner wird.
Die meisten Teile des FMZ-Plattform-API-Dokumentes verwenden JavaScript als Beispiel, aber aufgrund der Verkapselung gibt es fast keinen Unterschied zwischen den verschiedenen Sprachen, und Sie müssen nur auf Syntaxprobleme achten.
Da Python verschiedene Versionen hat, kann es zu Beginn des Programms angegeben werden, wie#!Python2
und#!Python3
. Beachten Sie, dass JavaScript kürzlich seine ES6-Syntax aktualisiert hat, und diejenigen, die daran interessiert sind, können darüber lernen. Die Python- und Javascript-Codes mit den gleichen Funktionen werden unten gezeigt. Es kann gesehen werden, dass es nur Syntaxunterschiede gibt, so dass das API-Dokument nur Beispiele von Javascript gibt, und dieses Tutorial berücksichtigt auch die speziellen Anwendungsfälle von Python.
#python code
def main():
while True:
Log(exchange.GetAccount().Balance)
Sleep(2000)
#the corresponding Js code
function main(){
while(true){
Log(exchange.GetAccount().Balance)
Sleep(2000)
}
}
Die FMZ Quant-Plattform bietet die
Das Strategieprogramm ist das gleiche wie ein normales Programm, das in Codeordern ausgeführt wird. Der besondere Teil ist, dass es eine
Weitere Funktionen mit Sondermaßnahmen sind wie folgt dargestellt:
function onTick(){
var ticker = exchange.GetTicker()
var account = exchange.GetAccount()
//write the strategy logic here, and it will be called ever 6 seconds
}
function main(){
while(true){
onTick()
Sleep(6000)
}
}
In dem vorherigen Beispiel kann die Strategie direkt gestoppt werden, wenn ein Fehler beim Netzwerkzugriff auftritt. Wenn Sie eine Strategie wünschen, die dem automatischen Neustart ähnelt und nicht stoppt, können Sie die fehlertolerante Hauptschleife
function onTick(){
var ticker = exchange.GetTicker()
var account = exchange.GetAccount()
//write the strategy logic here, and it will be called ever 6 seconds
}
function main(){
try{
while(true){
onTick()
Sleep(6000)
}
}catch(err){
Log(err)
}
}
Wenn bei der Erstellung eines Bots nur ein exchange
Zum Beispiel, wasexchange.GetTicker()
Der Marktticker dieses
FMZ Quant-Plattform unterstützt das Hinzufügen mehrerer exchanges
die sie repräsentieren, nämlichexchanges[0]
undexchanges[1]
... und so weiter, entsprechend der Reihenfolge, in der der Bot erstellt wird.BTC_USDT
, die ehemalige
Natürlich, wenn wir viele Handelspare betreiben, wird diese Methode sehr unbequem sein.exchange.SetCurrency("BTC_USDT")
dann wird das Handelspaar, das anexchange
wirdBTC_USDT
, die bis zum nächsten Aufruf zum Wechsel des Handelspares gültig bleibt.Beachten Sie, dass Backtest unterstützt Wechseln von Handelspaaren vor kurzemHier ein konkretes Beispiel:
var symbols = ["BTC_USDT", "LTC_USDT", "EOS_USDT", "ETH_USDT"]
var buyValue = 1000
function main(){
for(var i=0;i<symbols.length;i++){
exchange.SetCurrency(symbols[i])
var ticker = exchange.GetTicker()
var amount = _N(buyValue/ticker.Sell, 3)
exchange.Buy(ticker.Sell, amount)
Sleep(1000)
}
}
Wie im vorherigen Beispiel erwähnt, ist die Marktoberfläche im Allgemeinen eine öffentliche Schnittstelle, auf die jeder zugreifen kann. Die gängigen Marktoberflächen sind: GetTicker, GetDepth, GetRecords und GetTrades. Die Marktquote ist die Grundlage für die Strategie, um Handelsurteile zu treffen. Später werde ich sie einzeln vorstellen. Es ist besser, sie im
Jede Schnittstelle hat im allgemeinen eineInfo
Das Feld, das die ursprüngliche Datenfolge darstellt, die von der Plattform zurückgegeben wird, und das verwendet werden kann, um zusätzliche Informationen zu ergänzen.JSON.parse()
, während Python die json-Bibliothek verwendet.Time
In diesem Feld wird der Zeitstempel der Anfrage angegeben, mit dem die Verzögerung beurteilt werden kann.
Wenn Sie eine API im Bot verwenden, kann der Zugriff scheitern und zurückkehrennull
, und Python kehrt zurückNone
. Zu diesem Zeitpunkt werden die verwendeten Daten einen Fehler melden und den Bot zum Stillstand bringen, daher ist die Fehlerverträglichkeit sehr wichtig. Dieses Tutorial wird die Fehlerverträglichkeit speziell vorstellen.
GetTicker ist wahrscheinlich die am häufigsten verwendete Schnittstelle. Sie können den zuletzt ausgeführten Preis, den Buy1-Preis und den Sell1-Preis sowie das letzte Handelsvolumen finden. Bevor Sie eine Bestellung aufgeben, kann der ausgeführte Preis nach den Ticker-Informationen bestimmt werden. Ein Beispiel für eine Botsendung:{"Info:{}, "High":5226.69, "Low":5086.37,"Sell":5210.63, "Buy":5208.5, "Last":5208.51, "Volume":1703.1245, "OpenInterest":0, "Time":1554884195976}
.
function main() {
var ticker = exchange.GetTicker()
Log(ticker) //return ticker in the debugging tool, and you can see the specific result
Log('Last time executed price:',ticker.Last, 'Buy1 price:', ticker.Buy)
}
GetDepth, um die Tiefeninformationen über ausstehende Aufträge zu erhalten. Obwohl GetTicker die Preise von Buy 1 und Sell1 enthält, können Sie diese Schnittstelle verwenden, um im Allgemeinen 200 ausstehende Aufträge nach oben und unten zu überprüfen. Schockpreise können mithilfe dieser Schnittstelle berechnet werden. Im Folgenden finden Sie ein reales Rendite-Ergebnis. Unter ihnen steht
{
"Info":null,
"Asks":[
{"Price":5866.38,"Amount":0.068644},
{"Price":5866.39,"Amount":0.263985},
......
]
"Bids":[
{"Price":5865.13,"Amount":0.001898},
{"Price":5865,"Amount":0.085575},
......
],
"Time":1530241857399
}
Beispiel für die Verwendung von GetDepth für Asks & Bids:
function main() {
var depth = exchange.GetDepth()
Log('Buy 1 price:', depth.Bids[0].Price, 'Sell 1 price:', depth.Asks[0].Price)
}
GetRecords ist eine der am häufigsten verwendeten Schnittstellen, kann Preisinformationen in einem langen Zeitraum zur gleichen Zeit zurückgeben, was die Grundlage für die Berechnung verschiedener Indikatoren ist. Wenn die K-Linie-Periode nicht angegeben ist, bedeutet dies, den Standardzeitraum beim Hinzufügen eines Bots zu verwenden. Die Länge der K-Linie kann nicht angegeben werden, und sie wird im Laufe der Zeit weiter zunehmen. Die maximale Anzahl beträgt 2000 und im ersten Anruf beträgt die Zahl etwa 200 (verschiedene Plattformen geben unterschiedliche Zahlen zurück). Die letzte K-Linie ist die neueste K-Linie, so dass sich die Daten ändern, wenn sich die Marktkurse ändern; die erste K-Linie ist die älteste Daten.
exchange.SetMaxBarLen(Len)
kann die Anzahl der erstmals erworbenen K-Linien (von einigen Plattformen unterstützt) und die maximale Anzahl der K-Linien festlegen.Zum Beispiel:exchange.SetMaxBarLen(500)
.
GetRecords kann Perioden wie PERIOD_M1: 1 Minute, PERIOD_M5: 5 Minuten, PERIOD_M15: 15 Minuten, PERIOD_M30: 30 Minuten, PERIOD_H1: 1 Stunde und PERIOD_D1: 1 Tag angeben.exchange.GetRecords(PERIOD_M1)
. Nach dem Upgrade des neuesten Dockers wird es die Anpassung von Perioden unterstützen, die nur die zweite Zahl des Zeitraums als Parameter übergeben. Die Anpassung auf Minuteebene wird nach der 1-minütigen K-Linie synthetisiert, die K-Linie unter 1 Minute wird durch GetTrades ((() synthetisiert und die Rohstoff-Futures werden nach Tick synthetisiert.Beachten Sie, dass es auch andere volle Großbuchstaben-Variablen wiePERIOD_M1
Sie sind die standardmäßigen globalen Variablen von FMZ. Wenn Sie interessiert sind, können Sie
Beispiel für die Rückgabe von Daten:
[
{"Time":1526616000000,"Open":7995,"High":8067.65,"Low":7986.6,"Close":8027.22,"Volume":9444676.27669432},
{"Time":1526619600000,"Open":8019.03,"High":8049.99,"Low":7982.78,"Close":8027,"Volume":5354251.80804935},
{"Time":1526623200000,"Open":8027.01,"High":8036.41,"Low":7955.24,"Close":7955.39,"Volume":6659842.42025361},
......
]
Beispiel für eine wiederholte K-Linie:
function main(){
var close = []
var records = exchange.GetRecords(PERIOD_H1)
Log('total bars: ', records.length)
for(var i=0;i<records.length;i++){
close.push(records[i].Close)
}
return close
}
GetTrades erhält die Handelsdaten innerhalb eines bestimmten Zeitrahmens (nicht Ihre eigenen Handelsdaten), was von einigen Plattformen nicht unterstützt wird.
Diese Schnittstellen sind mit dem Konto verknüpft, so dass sie nicht direkt erhalten werden können. Um sie zu erhalten, müssen Sie API-Key verwenden, um zu signieren. Nach der einheitlichen automatischen Hintergrundverarbeitung der FMZ-Plattform können Sie sie direkt verwenden.
Als eine der am häufigsten verwendeten Schnittstellen muss sie vor der Bestellung aufgerufen werden, um unzureichendes Guthaben zu vermeiden.{"Stocks":0.38594816,"FrozenStocks":0,"Balance":542.858308,"FrozenBalance":0,"Info":{}}
Bei BTC_USDT
,
Beachten Sie, dass das Renditeergebnis das Ergebnis des angegebenen Handelspaares ist und die Informationen über andere Währungen im Handelskonto im Feld
Ein Bot, der ständig den Gesamtwert des aktuellen Handelspaares ausdruckt:
function main(){
while(true){
var ticker = exchange.GetTicker()
var account = exchange.GetAccount()
var price = ticker.Buy
var stocks = account.Stocks + account.FrozenStocks
var balance = account.Balance + account.FrozenBalance
var value = stocks*price + balance
Log('Account value is: ', value)
LogProfit(value)
Sleep(3000)//sleep 3000ms(3s), A loop must has a sleep, or the rate-limit of the exchange will be exceed
//when run in debug tool, add a break here
}
}
Kaufbestellungen.exchange.Buy(Price, Amount)
undexchange.Buy(Price, Amount, Msg)
, in dem null
wird zurückgegeben, wenn die Bestellung nicht erfolgreich ist, die zur Abfrage des Bestellstatus verwendet wird.
Wenn Sie eine Bestellung zum Marktpreis platzieren möchten, ist exchange.Buy(-1, 0.5)
; wenn das HandelspaarETH_BTC
Einige Plattformen unterstützen weder Marktordern noch Futures-Backtests.
Einige Plattformen haben die Präzisionsanforderungen für Preis und Menge, die mit der Präzisionsfunktion gesteuert werden können_N()
Für den Futures-Handel haben
Ein Beispiel für den Einkauf nach Erreichen des entsprechenden Preises:
function main(){
while(true){
var ticker = exchange.GetTicker()
var price = ticker.Sell
if(price >= 7000){
exchange.Buy(_N(price+5,2), 1, 'BTC-USDT')
break
}
Sleep(3000)//Sleep 3000ms
}
Log('done')
}
Die Parameter sind die gleichen wie exchange.Sell(-1, 0.2)
, bedeutet den Verkauf von 0,2 ETH zum Marktpreis.
GetOrder erhält die Auftragsinformationen basierend auf der Order-ID.exchange.GetOrder(OrderId)
, Type
und der tatsächliche AuftragswertStatus
Bei FMZ werden globale Konstanten verwendet, um diese Werte darzustellen.Status
der Wert eines unvollendeten Auftrags beträgt 0, was gleichbedeutend ist mitORDER_STATE_PENDING
. Alle diese globalen Konstanten können im Dokument angezeigt werden... Ergebnis zurückgegeben:
{
"Id":125723661, //Order id
"Amount":0.01, //Order ammount
"Price":7000, //Order price
"DealAmount":0, //Executed amount
"AvgPrice":0, //executed average price
"Status":0, //0: not completely executed; 1: executed; 2: canceled
"Type":1,//Order type; 0: buy order; 1: sell order
"ContractType":"",//contract type, used in futures trading
"Info":{} //the platform returns the raw information
}
}
Eine Strategie zum Kauf einer bestimmten Währungsmenge:
function main(){
while(true){
var amount = exchange.GetAccount().Stocks
var ticker = exchange.GetTicker()
var id = null
if(5-amount>0.01){
id = exchange.Buy(ticker.Sell, Math.min(5-amount,0.2))
}else{
Log('Job completed')
return //return the main function, bot will stop
}
Sleep(3000) //Sleep 3000ms
if(id){
var status = exchange.GetOrder(id).Status
if(status == 0){ //Here you can aslo use "status == ORDER_STATE_PENDING" to judge
exchange.CancelOrder(id)
}
}
}
}
GetOrder erhält die Liste aller unvollendeten Aufträge des aktuellen Handelspaares. Wenn keine unvollendete Bestellung vorhanden ist, wird ein leeres Array zurückgegeben. Das spezifische Ergebnis der Bestellliste, z. B.
Beispiel für die Stornierung aller Aufträge des aktuellen Handelspares:
function CancelAll(){
var orders = exchange.GetOrders()
for(var i=0;i<orders.length;i++){
exchange.CancelOrder(orders[i].Id) // cancel order by orderID
}
}
function main(){
CancelAll()
while(true){
//do something
Sleep(10000)
}
}
Laut der Bestell-ID, kündigen Sie die Bestellung.exchange.CancelOrder(OrderId)
. Wenn die Annullierung erfolgreich ist, wird
Für Kryptowährungen unterscheidet sich der Futures-Handel vom Spot-Handel. Die oben genannten Funktionen des Spot-Handels gelten auch für den Futures-Handel, und der Einzel-Futures-Handel hat seine eigenen Funktionen. Bevor Sie den Programmhandel mit Kryptowährungs-Futures durchführen, sollten Sie mit den manuellen Operationen auf der Website vertraut sein und die grundlegenden Konzepte wie offen, dicht, gekreuzt, isoliert, Hebelwirkung, naher Gewinn und Verlust, schwimmendes Einkommen, Marge und andere Konzepte sowie die entsprechenden Berechnungsformeln verstehen. Die entsprechenden Tutorials finden Sie auf verschiedenen Futures-Plattformen, und Sie müssen sie selbst lernen.
Dabei handelt es sich um eine Form der Vermarktung, bei der die Verkäufer die Verkäufe anbieten.
Wenn die Plattform sowohl Futures als auch Spot unterstützt, wie z. B. Futures von OKEX und Huobi, müssen Sie
Der erste Schritt beim Futures-Handel ist es, den zu handelnden Vertrag festzulegen. Nehmen Sie OKEX-Futures als Beispiel, wählen Sie ein BTC-Handelspaar aus, wenn Sie einen Bot oder Backtesting erstellen, und Sie müssen auch den wöchentlichen, nächsten Wochen- oder Quartalsvertrag im Code festlegen. Wenn er nicht festgelegt ist, wird er aufgefordertinvalid contract type
. Im Gegensatz zu Spot-Trading-Paaren verwenden Futures-Kontrakte häufig Handelswährung wie BTC als Margin. Das Hinzufügen von BTC zu einem Handelspaar stellt normalerweise ein BTC_USD-Handelspaar dar, das BTC als Margin verwendet. Wenn es einen Futures-Kontrakt mit USDT als Margin gibt, muss ein Bot erstellt werden, um BTC_USDT-Handelspaar hinzuzufügen. Zum Beispiel dauerhafte Kontrakte wie Binance OKEX Futures, mit sowohl Krypto-Margin- als auch USDT-Margin-Kontrakten.Nachdem Sie das Handelspaar eingestellt haben, müssen Sie auch den spezifischen Vertragstyp festlegen, z. B. dauerhaft, wöchentlich, nächste Woche usw. Nachdem Sie den Vertrag eingerichtet haben, können Sie Operationen wie das Erhalten von Marktnotierungen, Kauf und Verkauf durchführen.
Binance, OKEX, HuobiDM usw. verfügen sowohl über Krypto-Margin- als auch USDT-Margin-Kontrakte, die beim Hinzufügen eines Bots und Einstellen eines Vertrags unterschieden werden müssen.
//OKEX Futures
exchange.SetContractType("swap") // set to perpetual contract
exchange.SetContractType("this_week") // set to weekly contract
exchange.SetContractType("next_week") // set to next week contract
exchange.SetContractType("quarter") // set to quarterly contract
//HuobiDM
exchange.SetContractType("this_week") // set to weekly contract
exchange.SetContractType("next_week") // set to next week contract
exchange.SetContractType("quarter") // set to quarterly contract
exchange.SetContractType("swap") // set to perpetual contract
//Binance Futures
exchange.SetContractType("swap") // set to perpetual contract, and notice that crypto-margined and USDT-margined contracts are all in the perpetual contract
exchange.SetContractType("quarter") // set to quarterly contract
exchange.SetContractType("next_quarter") // set to next quarter contract
//BitMEX
exchange.SetContractType("XBTUSD") // set to perpetual contract
exchange.SetContractType("XBTM19") // the contract settled at a specific time; for more details, please log in BitMEX to check each contract code
//GateIO
exchange.SetContractType("swap") // set to perpetual contract, and do not set the default as swap perpetual contract
//Deribit
exchange.SetContractType("BTC-27APR18") // the contract settled at a specific time; for more details, please log in Deribit to check out
Um die aktuelle Positionsinformationsliste zu erhalten, können OKEX (OKCOIN) Futures einen Parameter übergeben, um den zu erhaltenden Vertragstyp anzugeben.[]
Die Positionsinformationen werden wie folgt zurückgegeben. Es gibt viele spezifische Informationen, die in Kombination mit dem Handelspaar analysiert werden müssen.
Datentyp | Name der Variablen | Beschreibung |
---|---|---|
Gegenstand | Informationen | die Rohstruktur, die die Plattform zurückgibt |
Zahl | Marginallevel | Hebelwirkung Größe; OKCoin ist 10 oder 20, und die gekreuzte Position von OK Futures gibt 10 (fest), für die Roh API unterstützt nicht |
Zahl | Betrag | Positionsbetrag; OKCoin gibt die Vertragsmenge an (ganzzahlige Zahl über 1) |
Zahl | Gefrierter Betrag | Betrag der eingefrorenen Position |
Zahl | Preis | Durchschnittlicher Kurs der Position |
Zahl | Marge | eingefrorene Grenze |
Zahl | Gewinn | Rohstoff-Futures: der Gewinn und Verlust der Positionsmarke auf dem Markt; Kryptowährung: Kryptowährungs-Einheit: BTC/LTC, traditionelle Futures-Einheit: RMB (Anmerkung:Im Falle einer gekreuzten Position von OKCoin-Futures bezieht sich dies auf den realisierten Gewinn und Verlust, nicht auf den Gewinn und Verlust der Position. Unter der isolierten Position bezieht es sich auf den Gewinn und Verlust der Position.) |
Verhaltensweise | Typ | PD_LONG ist eine Long-Position (CTP verwendet |
String | Vertragstyp | die Futures auf Rohstoffe sind Vertragscodes, und Aktien sind |
function main(){
exchange.SetContractType("this_week");
var position = exchange.GetPosition();
if(position.length>0){ //especially pay attention to judging the length of position before call, or an error will occur
Log("Amount:", position[0].Amount, "FrozenAmount:", position[0].FrozenAmount, "Price:",
position[0].Price, "Profit:", position[0].Profit, "Type:", position[0].Type,"ContractType:", position[0].ContractType)
}
}
Zunächst müssen Sie die Hebelgröße festlegen; Aufrufmethode:exchange.SetMarginLevel(10)
, wobei exchange.SetDirection(Direction)
, was offenen und geschlossenen Positionen entspricht.Im Gegensatz zu Futures, wenn ein dauerhafter Vertrag nicht hält die Konzepte von lang und kurz zur gleichen Zeit, dh eine einzige Position ist nicht erlaubt.buy
undsell
. Wenn es unterstützt Zwei-Wege-Positionen, müssen Sieclosebuy
, closesell
.Besondere Beziehungen:
Betrieb | SetDirection-Parameter | Funktion der Auftragserteilung |
---|---|---|
Offene Long-Position | Wechsel.SetDirection (( |
Austausch.Kauf() |
Schließen von Long-Positionen | Wechsel.SetDirection (( |
Austausch.Verkauf |
Offene Leerposition | Wechsel.SetDirection (( |
Austausch.Verkauf |
Schließung der Kurzposition | Wechsel.SetDirection (( |
Austausch.Kauf() |
Schließlich gibt es den spezifischen Code für offene und geschlossene Positionen. Die Menge der platzierten Aufträge variiert von Plattform zu Plattform. Zum Beispiel basieren Huobi-Futures auf der Anzahl der Vertragsmenge, und ein Vertrag beträgt 100 US-Dollar. Beachten Sie, dass Futures-Backtest Marktordern nicht unterstützt.
function main(){
exchange.SetContractType("this_week") // for example, set OKEX futures to weekly contract
price = exchange.GetTicker().Last
exchange.SetMarginLevel(10) // set to 10 times of leverage
exchange.SetDirection("buy") // set the order type as buy long
exchange.Buy(price+10, 20) // set contract quantity as 20 orders
pos = exchange.GetPosition()
Log(pos)
Log(exchange.GetOrders()) // check out if there is any unfinished order
exchange.SetDirection("closebuy"); // if it is a perpetual contract, directly set exchange.SetDirection("sell")
exchange.Sell(price-10, 20)
}
Geben Sie ein spezifisches Strategiebeispiel für vollständige Schließpositionen wie folgt an:
function main(){
while(true){
var pos = exchange.GetPosition()
var ticker = exchange.GetTicekr()
if(!ticker){
Log('not able to obtain ticker')
return
}
if(!pos || pos.length == 0 ){
Log('no position')
return
}
for(var i=0;i<pos.length;i++){
if(pos[i].Type == PD_LONG){
exchange.SetContractType(pos[i].ContractType)
exchange.SetDirection('closebuy')
exchange.Sell(ticker.Buy, pos[i].Amount - pos[i].FrozenAmount)
}
if(pos[i].Type == PD_SHORT){
exchange.SetContractType(pos[i].ContractType)
exchange.SetDirection('closesell')
exchange.Buy(ticker.Sell, pos[i].Amount - pos[i].FrozenAmount)
}
}
var orders = exchange.Getorders()
Sleep(500)
for(var j=0;j<orders.length;j++){
if(orders[i].Status == ORDER_STATE_PENDING){
exchange.CancelOrder(orders[i].Id)
}
}
}
}
Kryptowährungs-Leverage-Handel muss auf das Leverage-Konto im Code wechseln, und andere Teile sind wie Spot-Handel.
Verwendungexchange.IO("trade_margin") zum Wechsel in den Hebelkonto-Modus; die Platzierung einer Order und der Erwerb von Kontovermögen erhalten Zugriff auf die Schnittstelle der Hebelplattform. Verwendungexchange.IO("trade_normal") um wieder in den normalen Konto-Modus zu wechseln.
Unterstützte Plattformen:
Der Handel mit Rohstoff-Futures und Kryptowährungs-Futures unterscheidet sich ganz stark. Zunächst einmal ist die Handelszeit von Rohstoff-Futures sehr kurz, aber Kryptowährung wird 24 Stunden gehandelt; das Protokoll von Rohstoff-Futures ist keine häufig verwendete REST-API; die Handelsfrequenz und der ausstehende Auftragsbetrag von Rohstoff-Futures sind begrenzt, aber die von Kryptowährung sind sehr locker und so weiter. Daher gibt es viele Punkte, die bei dem Handel mit Rohstoff-Futures besondere Aufmerksamkeit erfordern, und es wird für diejenigen empfohlen, die eine reiche Erfahrung in manuellen Operationen haben. FMZ unterstützt jetzt Rohstoff-Futures-Simulationsbot, und Sie können sich auf:https://www.fmz.com/bbs-topic/325Für die Hinzufügung von Futures-Unternehmen:https://www.fmz.com/bbs-topic/371
Die Produktiv-Futures-Plattform hat im Juni 2019 eine durchsichtige Überwachung eingeführt; für einzelne Programme müssen einzelne Benutzer ein Konto eröffnen, um einen Autorisierungscode für Futures-Broker zu beantragen (die spezifische Anwendungsinformationsvorlage kann an die WeChat-Gruppe oder QQ-Gruppe gesendet werden), was in der Regel 4-5 Tage dauert; die Verfahren sind ziemlich kompliziert. Als programmatischer Handelsanbieter hat die FMZ-Plattform Software-Autorisationscodes von verschiedenen Futures-Dienstleistern beantragt. Benutzer können sie direkt ohne Beantragung verwenden.https://www.fmz.com/bbs-topic/3860. Wenn Ihr Futures-Broker nicht mehr auf der Liste ist, können Sie nur selbst bewerben oder ein neues Konto bei einem unterstützten Broker eröffnen, was in der Regel 2 Tage dauert. FMZ unterhält tiefgreifende Kooperationsbeziehungen mit einigen Dienstleistern; zum Beispiel hat Guotai Junan Hongyuan Futures die institutionelle Version der FMZ-Plattform gekauft, die von seinen Benutzern genutzt werden kann, und Benutzer werden automatisch ein VIP, wenn sie ein Konto eröffnen, und die Servicegebühr wird minimiert.https://www.fmz.com/bbs-topic/506.
Aufgrund der Vorteile der FMZ Quant-Plattformstruktur können Benutzer auch mehrere Futures-Broker-Konten hinzufügen und einige Funktionen implementieren, die andere Commodity-Futures-Handelssoftware nicht ausführen kann, wie die Synthese von Hochfrequenz-Tick; Sie können sich auf:https://www.fmz.com/bbs-topic/1184
Da es sich nicht um einen 24-Stunden-Handel handelt und ein Login erforderlich ist, ist es vor dem Handel notwendig, den Linkstatus zu beurteilen.exchange.IO("status")
isttrue
, was eine erfolgreiche Verbindung zur Plattform anzeigt. Wenn die API aufgerufen wird, wenn der Login nicht erfolgreich ist, wird _C(exchange.SetContractType,"MA888")
, die eine erfolgreiche Anmeldung gewährleistet.
Die Marktnotierungserwerbungs- und Handelscodes von Rohstoff-Futures sind die gleichen wie die von Kryptowährungs-Futures. Hier werden wir die Unterschiede und Punkte vorstellen, auf die man achten muss.
function main(){
_C(exchange.SetContractType,"MA888") //If you do not log in successfully, you cannot subscribe to the contract, so better to try again
while(true){
if(exchange.IO("status")){
var ticker = exchange.GetTicker()
Log("MA888 ticker:", ticker)
LogStatus(_D(), "Already connected with CTP !")//_D obtain event
} else {
LogStatus(_D(), "Not connected with CTP !")
Sleep(1000)
}
}
}
Es wird empfohlen, die Rohstoff-Futures-Bibliothek für den Handel zu verwenden (die später beschrieben wird), der Code wird zu diesem Zeitpunkt sehr einfach sein und es ist nicht notwendig, sich mit langweiligen Details zu befassen.https://www.fmz.com/strategy/57029
function main() {
// Use the CTA strategy framework of commodity futures library
$.CTA(Symbols, function(st) {
var r = st.records
var mp = st.position.amount
var symbol = st.symbol
/*
"r" represents K-line, "mp" indicates the position amount of the current variety; positive number means long position, negative number means short position, and 0 means no position; "symbol" is the variety name
if the return value is n:
n = 0 : full close positions (no matter now they are long or short)
n > 0 : if right now long positions are held, add n long positions; if now they are short positions, close n short posiitons; if n is over the position amount right now, reverse to open long positions
n < 0 : if right now short positions are held, add n short positions; if now they are long positions, close n long posiitons; if -n is over the position amount right now, reverse to open short positions
*/
if (r.length < SlowPeriod) {
return
}
var cross = _Cross(TA.EMA(r, FastPeriod), TA.EMA(r, SlowPeriod));
if (mp <= 0 && cross > ConfirmPeriod) {
Log(symbol, "Golden Cross Period", cross, "the moment position", mp);
return Lots * (mp < 0 ? 2 : 1)
} else if (mp >= 0 && cross < -ConfirmPeriod) {
Log(symbol, "Death Cross Period", cross, "the moment position", mp);
return -Lots * (mp > 0 ? 2 : 1)
}
});
}
Die Commodity-Futures verwenden das CTP-Protokoll, und alle Marktnotizen und Auftragsausführungen werden erst nach Änderungen benachrichtigt, während Abfragen zu Aufträgen, Konten und Positionen aktive Abfragen sind.GetTicker
, GetDepth
undGetRecords
, müssen alle Daten zwischengespeichert sein, um die neuesten Daten zu erhalten. Wenn keine Daten vorhanden sind, wartet es, bis es Daten gibt, so dass es nicht notwendig ist, dass die Strategie
Wenn Sie Daten jedes Mal erhalten möchten, wenn Sie die Marktkurse erhalten, auch wenn es sich um alte Daten handelt, können Sie zum sofortigen Aktualisierungsmodus der Marktkurse wechselnexchange.IO("mode", 0)
. Zu diesem Zeitpunkt kann die Strategie nicht als ereignisgesteuert geschrieben werden, und ein exchange.IO("mode", 1)
um wieder in den Standard-Cache-Modus zu wechseln.
Bei der Ausführung eines einzigen Vertrags verwenden Sie den Standardmodus. Wenn es jedoch mehrere Verträge gibt, ist es möglich, dass einer der Verträge die Marktbeiträge nicht aktualisiert, was zu einer Schnittstellenblockade für den Erhalt von Marktbeiträgen führt, und die Quote-Updates anderer Verträge können auch nicht erhalten werden. Um dieses Problem zu lösen, kann der sofortige Update-Modus verwendet werden, aber es ist unbequem, Hochfrequenzstrategien zu schreiben. Zu diesem Zeitpunkt können Sie den Event-Push-Modus verwenden, um den Push von Aufträgen und Zitaten zu erhalten.exchange.IO("wait")
Wenn mehrere Tauschobjekte hinzugefügt werden, was in Rohstoff-Futures selten ist, können Sieexchange.IO("wait_any")
, und der zurückgegebene
Schub von Markt-Tick-Veränderungen:{Event:"tick", Index: platform index (in the order of the platforms added in the bot), Nano: event of nanosecond-level time, Symbol: contract name}
Bestellschub:{Event:"order", Index:Exchange index, Nano:Event of nanosecond-level time, Order:Order information (same as GetOrder)}
Zu diesem Zeitpunkt kann die Strategiestruktur wie folgt geschrieben werden:
function on_tick(symbol){
Log("symbol update")
exchange.SetContractType(symbol)
Log(exchange.GetTicker())
}
function on_order(order){
Log("order update", order)
}
function main(){
while(true){
if(exchange.IO("status")){ //Judge the link status
exchange.IO("mode", 0)
_C(exchange.SetContractType, "MA888")//Subscribe to MA; only the subscription request for the first time is ture, and the later ones are program switches, which do not consume time
_C(exchange.SetContractType, "rb888")//Subscribe to rb
while(true){
var e = exchange.IO("wait")
if(e){
if(e.event == "tick"){
on_tick(e.Symbol)
}else if(e.event == "order"){
on_order(e.Order)
}
}
}
}else{
Sleep(10*1000)
}
}
}
Beachten Sie auch den Unterschied zwischen Rohstoff-Futures und Kryptowährungsplattformen. Zum Beispiel hat
exchange.IO("Instrumente"): es gibt die Liste aller Verträge auf der Plattform {Vertragsname: Details} in Wörterbuchform zurück und unterstützt nur Bots.exchange.IO("Produkte"): es gibt die Liste aller Artikel der Plattform {Name des Vertrags: Details} in Wörterbuchform zurück und unterstützt nur Bots.exchange.IO("abonniert"): es gibt die abonnierten Marktkurse auf der Plattform in Wörterbuchform zurück und unterstützt nur Bots.
DieContractType
Bei den traditionellen CTP-Futures bezieht sich die Kontrakt-ID, die für Groß- und Kleinbuchstaben sensibel ist.exchange.SetContractType("au1506")
. Nachdem der Vertrag erfolgreich eingestellt wurde, wird er die detaillierten Informationen des Vertrages zurückgeben, wie zum Beispiel den Mindestkaufbetrag, die Servicegebühr, die Lieferzeit usw. Bei der Abonnement von mehreren Verträgen wird nur das erste Mal eine Abonnementanfrage tatsächlich gesendet, und dann wird das Handelspaar einfach auf Code-Ebene gewechselt, was keine Zeit in Anspruch nimmt. Der wichtigste kontinuierliche Vertrag ist Code 888, wie MA888, der kontinuierliche Tarifvertrag ist 000, wie MA000; 888 und 000 sind virtuelle Vertragsgeschäfte, die nur Backtest unterstützen, und echte Bots unterstützen nur Marktnotierungen.Mylanguage kann jedoch den Hauptvertrag betreiben, und das Programm ändert automatisch Positionen, d. h. schließt die nicht Hauptpositionen und eröffnet neue Positionen auf den Hauptpositionen.
Ein erfolgloser Login kann keine Verträge einrichten, sondern kehrt sofort zurück, so dass Sie erneut mit
Die SetDirection
kann vier Parameter erhalten:buy, closebuy, sell, closesell
. Rohstofffutures haben mehrclosebuy_today
undclosesell_today
, der die Schließung der aktuellen Positionen anzeigt;closebuy/ closesell
, was das Schließen der Positionen von gestern anzeigt; nur die Varianten der Shanghai Futures Exchange sind in das Schließen von heute und das Schließen von gestern unterteilt, was sich auf die Servicegebühr auswirken kann, so dass es notwendig ist, dem Schließen der Positionen von gestern Priorität zu geben. Für traditionelle CTP-Futures können Sie den zweiten Parameter als
Betrieb | SetDirection-Parameter | Funktion der Auftragserteilung |
---|---|---|
Offene Long-Position | Wechsel.SetDirection (( |
Austausch.Kauf() |
Schließen von Long-Positionen | Wechsel.SetDirection (( |
Austausch.Verkauf |
Offene Leerposition | Wechsel.SetDirection (( |
Austausch.Verkauf |
Schließung der Kurzposition | Wechsel.SetDirection (( |
Austausch.Kauf() |
Das folgende Beispiel ist eine spezifische Schlusspositionfunktion. Beachten Sie, dass dieses Beispiel zu einfach ist. Sie sollten auch berücksichtigen, ob es innerhalb der Handelszeit ist, wie Sie die ausstehende Bestellung erneut ausprobieren können, wenn sie nicht vollständig ausgefüllt ist, was ist das maximale Auftragsvolumen, ob die Häufigkeit zu hoch ist und ob es sich um einen gleitenden Preis oder Marktpreis und so weiter handelt. Nur zur Referenz,es ist ein Bibliothekspaket der vorgeschlagenen Plattformen für die Eröffnung und Schließung von Positionen in echten Bots:https://www.fmz.com/strategy/12961In der Bibliothekssection gibt es eine spezifische Einführung und es wird empfohlen, die Quellcodes der Bibliothek zu studieren.
function Cover(contractType, amount, slide) {
for (var i = 0; i < positions.length; i++) {
if (positions[i].ContractType != contractType) {
continue;
}
var depth = _C(e.GetDepth);
if (positions[i].Type == PD_LONG || positions[i].Type == PD_LONG_YD) {
exchange.SetDirection(positions[i].Type == PD_LONG ? "closebuy_today" : "closebuy");
exchange.Sell(depth.Bids[0]-slide, amount, contractType, positions[i].Type == PD_LONG ? "Close today" : "Close yesterday", 'Bid', depth.Bids[0]);
} else {
exchange.SetDirection(positions[i].Type == PD_SHORT ? "closesell_today" : "closesell");
exchange.Buy(depth.Asks[0]+slide, amount, contractType, positions[i].Type == PD_SHORT ? "Close today" : "Close yesterday", 'Ask', depth.Asks[0]);
}
}
}
Futures auf Rohstoffe unterstützen kundenspezifische Auftragsarten (Bots unterstützt, Backtest nicht), die durch ein Suffix angegeben werden, das an
exchange.SetDirection("buy_ioc");
exchange.SetDirection("sell_gtd-20170111")
Besondere Suffixe:
Standardmäßig sind die in den Commodity Futures Brokern geöffneten Schnittstellen alle CTP-Schnittstellen. Bei Bedarf können sie durch Esunny-Schnittstellen ersetzt werden. Durch die Verkapselung von FMZ ist die Aufrufmethode die gleiche. Der Unterschied besteht darin, dass Konten, Aufträge und Positionen alle im Push-Modus sind, so dass der Docker diese Daten lokal aufbewahrt und sofort zurückkehrt, wenn die entsprechende Schnittstelle aufgerufen wird, ohne tatsächlich eine Anfrage zu stellen.
Esunny-Protokoll-Sonderbestellungen sind:
Wenn Sie einen Protokolldatensatz auf der Bot-Schnittstelle protokollieren und das Zeichen Log('Push to WeChat@')
.
Die Farbe des Logs kann auch angepasst werden, wieLog('this is a log in red font #ff0000')
.
#ff0000
ist die Hexadezimalzahl der RGB-Farbe, die anzeigt, dass alle Protokolldateien in der SqLit-Datenbank des Bots im Verzeichnis gespeichert sind, in dem sich der Docker befindet, der mit Datenbanksoftware heruntergeladen und geöffnet werden kann oder zum Kopieren und Wiederherstellen von Sicherungen verwendet werden kann (Datenbankname und Bot-ID sind identisch).
Es zeichnet die Gewinne auf und zeichnet die Gewinnkurve auf der Bot-Schnittstelle, die beibehalten werden kann, nachdem der Bot neu gestartet wurde.LogProfit(1000)
. Beachten Sie, dass der Parameter vonLogProfit
ist nicht unbedingt der Gewinn, und es kann jede Zahl sein und muss von sich aus ausgefüllt werden.
Wenn der Bot-Status, da das Protokoll zuerst gespeichert und kontinuierlich aktualisiert wird, die Informationen nur zur Anzeige benötigt, nicht zur Speicherung, können Sie dieLogStatus
Die Parameter derLogStatus
sind Zeichenfolgen, die auch zur Darstellung der Tabelleninformationen verwendet werden können.
Ein Beispiel für eine spezifische Tabelle zur Anzeige der realen Position eines Bots:
var table = {type: 'table', title: 'position information', cols: ['Column1', 'Column2'], rows: [ ['abc', 'def'], ['ABC', 'support color #ff0000']]};
LogStatus('`' + JSON.stringify(table) + '`'); // After serialization, JSON will be added the character "'" on both sides, which is regarded as a comlpex messag format (now supporting tables)
LogStatus('The first line information\n`' + JSON.stringify(table) + '`\nthe third line information'); // the table information can be displayed in multiple lines
LogStatus('`' + JSON.stringify([table, table]) + '`'); // Multiple tables are supported to be displayed at the same time, which will be displayed in one group by TAB
LogStatus('`' + JSON.stringify(tab1) + '`\n' + '`' + JSON.stringify(tab2) + '`\n