OANDA API, Python】ランダム自動売買プログラムを作る 〜AIを使った自動売買に向けて〜

AIを使った自動売買プログラムを作るための手始めとして、OANDA APIとPythonを使ってランダム自動売買プログラムを作ってみます。

方針

今回作るプログラムの基本的な方針としては、

  • 一度に持つポジションは1つ
  • エントリー時に逆指値を指定

とします。
エントリー時に逆指値を指定するので、特に決済処理は書きません。

準備

環境

まず、私の環境は

  • python 3.8
  • oandapyV20 : 0.6.3

です。

OANDA APIを使うための環境構築

今回はOANDA APIを使います。

OANDA APIを使うためにデモ、もしくは本番口座を作成して、アクセストークンを取得しておく必要があります。以下の記事を参考にしてください。

また、oandapyV20をpipでインストールしておく必要があります。pipで簡単にインストールできます。

pip install oandapyV20

実装

では、実装していきます。

まず、必要なモジュール群をimportしておきます。

import oandapyV20
import oandapyV20.endpoints.orders as orders
import oandapyV20.endpoints.positions as positions
import oandapyV20.endpoints.instruments as instruments

import time
import schedule
import numpy as np
import pandas as pd

oanda apiへの窓口を用意しておきます。ここで、アクセストークンとアカウントIDを使います。

client = oandapyV20.API(access_token="******************")
account_id = "**********************"

定数も定義しておきます。

MARGIN = 0.1
STAY, BUY, SELL = 0, 1, 2

MARGINは逆指値を決定するときに使います。
また、STAY, BUY, SELLはそれぞれ、何もしない、買う、売るという選択肢とします。

次に現在の為替データを取得します。
必要ないですが、 bidとaskの両方を取得しておきます。

def get_candles():
    params = {
        "granularity": "M5",
        "count": 100,
        "price": "",
    }
    candles = None
    for price in ["A", "B"]:
        params["price"] = price
        instruments_candles = instruments.InstrumentsCandles(
            instrument="USD_JPY", params=params)
        response = client.request(instruments_candles)
        if candles is None:
            candles = pd.DataFrame(response["candles"])
            candles = candles.set_index(candles["time"])
        else:
            new_candle = pd.DataFrame(response["candles"])
            new_candle = new_candle.set_index(new_candle["time"])
            candles["bid"] = new_candle["bid"]

    return candles

ここの為替データの取得に関してはこの記事を参照してください。

次にオーダーをするメソッドを作成します。

def order(action, client, candles):

    close_value = float(candles.bid.iloc[-1]["c"])
    upperprice = str((round(close_value+MARGIN, 3)))
    lowerprice = str((round(close_value-MARGIN, 3)))

    data = {
        "order": {
            "instrument": "USD_JPY",
            "type": "MARKET",
        }
    }

    if action == BUY:
        data["order"]["units"] = "+1"
        data["order"]["stopLossOnFill"] = {
            "timeInForce": "GTC",
            "price": lowerprice
        }
        data["order"]["takeProfitOnFill"] = {
            "timeInForce": "GTC",
            "price": upperprice
        }

    elif action == SELL:
        data["order"]["units"] = "-1"
        data["order"]["stopLossOnFill"] = {
            "timeInForce": "GTC",
            "price": upperprice
        }
        data["order"]["takeProfitOnFill"] = {
            "timeInForce": "GTC",
            "price": lowerprice
        }
    else:
        return None

    r = orders.OrderCreate(account_id, data=data)
    result = client.request(r)

    if action == BUY:
        print("price:{}, tp:{}, sl:{}, id:{}".format(
            result["positions"][0]["long"]["averagePrice"], upperprice, lowerprice, result["positions"][0]["long"]["tradeIDs"][0]))
    elif action == SELL:
        print("price:{}, tp:{}, sl:{}, id:{}".format(
            result["positions"][0]["short"]["averagePrice"], upperprice, lowerprice, result["positions"][0]["short"]["tradeIDs"][0]))

まず、3〜4行目で直近の終値を取得し、利確、ロスカットで使う逆指値(upperprice, lowerprice)を設定します。

7行目からorderに必要なデータをdict形式で作成します。

買いと売りのときで逆指値が変わるのでif分で分けておきます。

ちなみに、takeProfitOnFillが利確価格、stopLossOnFillがロスカット価格になります。

38、39行目でオーダーを実行しています。

次に定期的に呼び出すmain関数を作成します。このメソッドに先程までに作成したメソッドを加えていきます。

def main():
    """
        定期的に売買を実行する
    """
    # 現在のポジションの確認
    r = positions.OpenPositions(account_id)
    result = client.request(r)
    positions_ = result["positions"]

    candles = get_candles()

    # ポジションがなければ取引を行う
    if len(positions_) == 0:
        action = np.random.randint(3)
        order(action, client, candles)

まず、6行目〜8行目で、現在の保有ポジションを取得します。

13行からは、現在保有しているポジションがなければ、トレードをするかを決定します。
現状はランダムで決めています。

最後にmain関数を定期的に呼び出すコードを書きます。

schedule.every(1).minutes.do(main)

while True:
    schedule.run_pending()
    time.sleep(1)

ここまでのコードを書いて実行すると1分毎に自動でトレードするようになります。

全コード

最後に全コードを上げておきます。

import oandapyV20
import oandapyV20.endpoints.orders as orders
import oandapyV20.endpoints.positions as positions
import oandapyV20.endpoints.instruments as instruments

import time
import schedule
import numpy as np
import pandas as pd


client = oandapyV20.API(
    access_token="********************")
account_id = "*********************"

MARGIN = 0.1
STAY, BUY, SELL = 0, 1, 2

def get_candles():
    params = {
        "granularity": "M5",
        "count": 100,
        "price": "",
    }
    candles = None
    for price in ["A", "B"]:
        params["price"] = price
        instruments_candles = instruments.InstrumentsCandles(
            instrument="USD_JPY", params=params)
        response = client.request(instruments_candles)
        if candles is None:
            candles = pd.DataFrame(response["candles"])
            candles = candles.set_index(candles["time"])
        else:
            new_candle = pd.DataFrame(response["candles"])
            new_candle = new_candle.set_index(new_candle["time"])
            candles["bid"] = new_candle["bid"]

    return candles


def order(action, client, candles):

    close_value = float(candles.bid.iloc[-1]["c"])
    upperprice = str((round(close_value+MARGIN, 3)))
    lowerprice = str((round(close_value-MARGIN, 3)))

    data = {
        "order": {
            "instrument": "USD_JPY",
            "type": "MARKET",
        }
    }

    if action == BUY:
        data["order"]["units"] = "+1"
        data["order"]["stopLossOnFill"] = {
            "timeInForce": "GTC",
            "price": lowerprice
        }
        data["order"]["takeProfitOnFill"] = {
            "timeInForce": "GTC",
            "price": upperprice
        }

    elif action == SELL:
        data["order"]["units"] = "-1"
        data["order"]["stopLossOnFill"] = {
            "timeInForce": "GTC",
            "price": upperprice
        }
        data["order"]["takeProfitOnFill"] = {
            "timeInForce": "GTC",
            "price": lowerprice
        }
    else:
        return None

    r = orders.OrderCreate(account_id, data=data)
    result = client.request(r)

    if action == BUY:
        print("price:{}, tp:{}, sl:{}, id:{}".format(
            result["positions"][0]["long"]["averagePrice"], upperprice, lowerprice, result["positions"][0]["long"]["tradeIDs"][0]))
    elif action == SELL:
        print("price:{}, tp:{}, sl:{}, id:{}".format(
            result["positions"][0]["short"]["averagePrice"], upperprice, lowerprice, result["positions"][0]["short"]["tradeIDs"][0]))


def main():
    """
        定期的に売買を実行する
    """
    # 現在のポジションの確認
    r = positions.OpenPositions(account_id)
    result = client.request(r)
    positions_ = result["positions"]

    candles = get_candles()

    # ポジションがなければ取引を行う
    if len(positions_) == 0:
        action = np.random.randint(3)
        order(action, client, candles)


schedule.every(1).minutes.do(main)

while True:
    schedule.run_pending()
    time.sleep(1)

終わりに

今回はAIを使った自動売買プログラムの手始めとして、ランダム自動売買プログラムを作ってみました。

ランダムなので必ずデモ口座でやってください(笑)。さすがにこれを実践投入するのは危なすぎるので(汗)

なんとか自動売買プログラムを今後作っていきたいと思います!

ちなみに本サイトでは、ニューラルネットワークで為替データの予測するプログラムの作成方法などをも紹介していますので、ぜひ見てみてください

タイトルとURLをコピーしました