[PYTHON] Neuerstellung eines Auftrags- / Positionsbuchs mit oandapy V20

1. Zuallererst

Ich denke, dass viele Leute nur den Preis (+ Volumen) verwenden, wenn sie Investment-Bots erstellen. Dies sind jedoch nicht die einzigen verfügbaren Daten. Beispielsweise können der Status von Aufträgen und der Status von Haltepositionen berücksichtigt werden.

Dieses Mal habe ich Bestell- und Positionsdaten (Auftragsbuch, Positionsbuch) von oanda of FX Exchange herausgenommen und ein Tool zur Verarbeitung erstellt, damit ich sie weitergeben kann.

2. Was ist ein Auftragsbuch / Positionsbuch?

Das Auftragsbuch zeigt, wie viele nicht erfüllte Bestellungen für jeden Tarif vorhanden sind (Board auf Lager). Offene Positionen geben an, wie viele Positionen derzeit mit welcher Rate gehalten werden. Für Details springen Sie bitte über den Link zur Oanda-Site und überprüfen Sie.

スクリーンショット 0002-09-22 16.28.46.png ( https://www.oanda.jp/lab-education/oanda_lab/oanda_rab/open_position/ )

3. Über Oandas Buch

Mit Transaktionen im Wert von über 500.000 USD innerhalb des letzten Monats aktualisiert oanda alle 5 Minuten Ihr Auftragsbuch und Ihr Positionsbuch. Diese Häufigkeit ändert sich nicht, ob Sie sie im Web anzeigen oder mit API abrufen.

Wenn Sie nur ein Konto erstellen, sinkt die Aktualisierungshäufigkeit alle 20 Minuten auf einmal. Wenn Sie jedoch nicht häufig handeln, ist dies meiner Meinung nach eine ausreichende Aktualisierungshäufigkeit.

Wir werden hier nicht erklären, wie man ein Konto eröffnet oder einen API-Schlüssel erhält.

4. Körper

Sie können sehen, dass die offenen Aufträge, die Sie auf der Oanda-Website sehen, um eine bestimmte Breite (alle 0,05 Yen für Dollar-Yen) verteilt sind, die auf dem Kurs zum Zeitpunkt der Erstellung des Schnappschusses des offenen Auftrags zentriert ist.

Aber die von api erhaltenen Daten sind nicht so. Das Auftragsbuch enthält eine breite Palette von Kursinformationen, einschließlich Informationen, die in der Realität unmöglich sind, z. B. 1 Dollar = 0 Yen bis 1 Dollar = 200 Yen. Auch die Rate im Herzen offener Aufträge schwankt ständig. Selbst wenn Sie versuchen, die erhaltenen Daten so zu analysieren, wie sie sind, können Sie daher nicht sehen, wie weit jede Rate von der Rate entfernt ist, als die offene Bestellung erstellt wurde.

Aus diesem Grund haben wir dieses Mal einen Code vorbereitet, mit dem Daten erfasst und verarbeitet werden können, damit Sie die zentrale Rate und deren Entfernung intuitiv erfassen können (siehe Abbildung unten). Bitte schreiben Sie die accountID und access_token in Ihre eigene.

スクリーンショット 0002-09-22 17.06.44.png

Es scheint keine Daten vor dem 20. Januar 2017 zu geben. Außerdem dauert es ungefähr 20 bis 30 Minuten, um das Buch jede Stunde zu erhalten.

def fetch_orderbook(instrument="USD_JPY", levels = 5, timeframe="15m"):
  '''
  instrument :Name des Währungspaares
  levels :Wie viele hoch (runter), um von der zentralen Rate zu bekommen, >0
  timeframe :Wie viele Minuten, um das Buch zu bekommen, "m":minute, "H":hour, "D":day, >="5m"
              ex) "1H":Holen Sie sich jede Stunde, "2D":Holen Sie sich täglich
  '''
  accountID = "×××-×××-×××-×××"
  access_token ="××××××××××××"
  api = API(access_token=access_token, environment="live")

  if timeframe[-1]=="m":
    diff = 60 * int(timeframe[:-1])
  elif timeframe[-1]=="H":
    diff = 60 * 60 * int(timeframe[:-1])
  elif timeframe[-1]=="D":
    diff = 60 * 60 * 24 * int(timeframe[:-1])
    
  timestamp = datetime.datetime(year=2017, month=1, day=20)
  now = datetime.datetime.utcnow()
  processed_book, book_timestamps = [], []
  counter = 0
  start = datetime.datetime.utcnow()
  while True:
    try:
      #Beenden Sie, wenn Sie bis jetzt fertig sind
      if now < timestamp:
        break
      #Verhinderung eines übermäßigen Zugriffs auf den Server und die Protokollausgabe
      counter+=1
      if counter%100==0:
        print(timestamp, datetime.datetime.utcnow()-start)
        start = datetime.datetime.utcnow()
        counter=0
        time.sleep(1)
      
      #Auftragsbuch erhalten
      r=instruments.InstrumentsOrderBook(instrument=instrument, params={"time":timestamp.strftime("%Y-%m-%dT%H:%M:00Z")})
      api.request(r)
      book_created_rate, buckets, book_created_time = float(r.response["orderBook"]["price"]), r.response["orderBook"]["buckets"], r.response["orderBook"]["time"]
      #Erhalten Sie einen Index, der dem Kurs zum Zeitpunkt der Bucherstellung nahe kommt
      bucket_rate = [round(float(b["price"]), 2) for b in buckets]
      upper_idx = np.searchsorted(bucket_rate, book_created_rate)
      lower_idx = upper_idx - 1
      #Vom aktuellen Preis getrennte Ebenen hinzugefügt
      row_book = [book_created_rate]
      for i in range(levels):
        upper, lower = buckets[upper_idx + i], buckets[lower_idx - i]
        bucket = [upper["price"], upper['longCountPercent'], upper['shortCountPercent'], 
                  lower["price"], lower['longCountPercent'], lower['shortCountPercent']]
        bucket = [float(num) for num in bucket]
        row_book.extend(bucket)
      processed_book.append(row_book)
      book_timestamps.append(book_created_time)
    except:
      #Samstag und Sonntag
      pass
    timestamp+=datetime.timedelta(seconds = diff)


  #Spaltenname
  column_names = ["rate"]
  for i in range(levels):
    column_names.extend(["price_+{}".format(i+1), "OrderLongPercent_+{}".format(i+1), "OrderShortPercent_+{}".format(i+1),
    "price_-{}".format(i+1), "OrderLongPercent_-{}".format(i+1), "OrderShortPercent_-{}".format(i+1)])

  #Daten kombinieren
  orderbook = pd.DataFrame(processed_book, columns=column_names, index=book_timestamps)
  return orderbook

Gleiches gilt für das Positionsbuch

def fetch_positionbook(instrument="USD_JPY", levels = 5, timeframe="15m"):
  '''
  instrument :Name des Währungspaares
  levels :Wie viele hoch (runter), um von der zentralen Rate zu bekommen, >0
  timeframe :Wie viele Minuten, um das Buch zu bekommen, "m":minute, "H":hour, "D":day, >="5m"
              ex) "1H":Holen Sie sich jede Stunde, "2D":Holen Sie sich täglich
  '''
  accountID = "×××-×××-×××-×××"
  access_token ="××××××××××××"
  api = API(access_token=access_token, environment="live")

  if timeframe[-1]=="m":
    diff = 60 * int(timeframe[:-1])
  elif timeframe[-1]=="H":
    diff = 60 * 60 * int(timeframe[:-1])
  elif timeframe[-1]=="D":
    diff = 60 * 60 * 24 * int(timeframe[:-1])
    
  timestamp = datetime.datetime(year=2017, month=1, day=20)
  now = datetime.datetime.utcnow()
  processed_book, book_timestamps = [], []
  counter = 0
  start = datetime.datetime.utcnow()
  while True:
    try:
      #Beenden Sie, wenn Sie bis jetzt fertig sind
      if now < timestamp:
        break
      #Verhinderung eines übermäßigen Zugriffs auf den Server und die Protokollausgabe
      counter+=1
      if counter%100==0:
        print(timestamp, datetime.datetime.utcnow()-start)
        start = datetime.datetime.utcnow()
        counter=0
        time.sleep(1)
      
      #Holen Sie sich das Positionsbuch
      r=instruments.InstrumentsPositionBook(instrument=instrument, params={"time":timestamp.strftime("%Y-%m-%dT%H:%M:00Z")})
      api.request(r)
      book_created_rate, buckets, book_created_time = float(r.response["positionBook"]["price"]), r.response["positionBook"]["buckets"], r.response["positionBook"]["time"]
      #Erhalten Sie einen Index, der dem Kurs zum Zeitpunkt der Bucherstellung nahe kommt
      bucket_rate = [round(float(b["price"]), 2) for b in buckets]
      upper_idx = np.searchsorted(bucket_rate, book_created_rate)
      lower_idx = upper_idx - 1
      #Vom aktuellen Preis getrennte Ebenen hinzugefügt
      row_book = [book_created_rate]
      for i in range(levels):
        upper, lower = buckets[upper_idx + i], buckets[lower_idx - i]
        bucket = [upper["price"], upper['longCountPercent'], upper['shortCountPercent'], 
                  lower["price"], lower['longCountPercent'], lower['shortCountPercent']]
        bucket = [float(num) for num in bucket]
        row_book.extend(bucket)
      processed_book.append(row_book)
      book_timestamps.append(book_created_time)
    except:
      #Samstag und Sonntag
      pass
    timestamp+=datetime.timedelta(seconds = diff)


  #Spaltenname
  column_names = ["rate"]
  for i in range(levels):
    column_names.extend(["price_+{}".format(i+1), "PositionLongPercent_+{}".format(i+1), "PositionShortPercent_+{}".format(i+1),
    "price_-{}".format(i+1), "PositionLongPercent_-{}".format(i+1), "PositionShortPercent_-{}".format(i+1)])

  #Daten kombinieren
  positionbook = pd.DataFrame(processed_book, columns=column_names, index=book_timestamps)
  return positionbook

5. Schließlich

Ich würde es gerne vorstellen, aber ich denke, es ist schwierig, einen Bot nur mit diesen Daten zu erstellen. Ich konnte gewinnen (ohne die Gebühr), aber ich konnte nicht mit der Gebühr gewinnen. Vielleicht funktioniert es gut, wenn es mit der Zeitanomalie kombiniert wird ...?

Recommended Posts

Neuerstellung eines Auftrags- / Positionsbuchs mit oandapy V20