APIの使い方

TradingViewとOANDA証券の「API」を組み合わせた自動売買システムの構築方法


TradingViewとOANDAのREST API(以下、API)を組み合わせて自動売買システムを構築する方法について解説します。

TradingViewは、アメリカ・シカゴに本社を置くTradingView社によって開発された、豊富な分析機能を有するチャートツールです。

チャート分析に利用できるたくさんのツールが備わっており、世界中のトレーダーに利用されています。

FXの分析はもちろん、株や仮想通貨など、あらゆる金融商品に対応しているのも大きな特徴です。

TradingViewの機能の1つに、設定した条件を満たすと自動でアラートを送信する、シグナル通知があります。

この通知はWebhookで受け取ることが可能で、これを利用すれば Webhookでシグナル通知を受け取り、内容に応じてAPIを介して売買注文を出すことが可能になります。

本記事では、ngrokを使ってWebhook通知を受け取るシステムを構築し、通知内容に応じてAPIで売買注文を出すシステムを構築していきます。

APIの実装はPythonで行います。

TradingViewを利用すれば、必要なインディケーターの計算やストラテジーの実装が不要になるため、開発コストを大きく下げることが可能です。

事前準備

まずは必要となるアカウントやソフトウェアの用意をします。

必要なものは次の3つです。

  • 1.OANDAのAPIキー
  • 2.TradingViewのアカウント(Pro以上)
  • 3.ngrokのアカウント作成とインストール

OANDAのAPIキー

PythonでAPIを利用するためには、次の2点が必要です。

  • 1.APIトークンの発行
  • 2.oandapyV20のインストール

詳細についてはこちらの記事で解説しておりますのでご参照ください。

Pythonで「REST API」を使用するまでの4つの手順について解説

TradingViewのアカウント(Pro以上)

次にTradingViewのアカウントを用意します。

TradingViewの公式サイトからアカウント登録を行なってください。

GoogleやTwitterアカウントなどで作成することもできます。

GoogleやTwitterアカウントなどで作成することも可能

Webhookによるアラート通知を受け取るためには、Pro以上の有料会員になる必要があります。

2022年11月現在では、Proの料金は月額$14.95(年払いなら月額$10.50)です。

30日間の無料トライアルもあります。

30日間の無料トライアル

ngrokのアカウント作成とインストール

最後にngrokを用意します。

ngrokを使えば、ローカルPCで稼働しているネットワーク(TCP)サービスを外部ネットワークへ公開することができます。

まずはngrokの公式サイトからアカウントの登録を行います。

必要な項目を入力してアカウントを作成してください。

必要な項目を入力してアカウントを作成

アカウントの作成が完了したら、ngrokをインストールしていきます。

本記事では、Mac環境によるインストール方法をご紹介します。

こちらに手順がありますので、これに従ってインストールを行います。

Macの場合、Homebrewでngrokをインストールすることが可能です。

ターミナルを開いて次のコマンドを実行してngrokをインストールします。



brew install ngrok/ngrok/ngrok


しばらく待つとインストールが完了します。

インストールが完了

次にアカウントの認証を行います。

ngrokの管理画面からauthtokenを確認することができます。

こちらを利用して認証作業を行います。

認証作業

ターミナルで次のコマンドを実行してアカウントの認証を行なってください。



ngrok config add-authtoken 


認証が完了すると、ngrokのサービスが利用できるようになります。

これでngrokの準備は完了です。

TradingView, ngrok, OANDAのAPIで自動売買システムを構築する

それでは必要なツールの準備が整ったので、ここから自動売買システムを構築していきます。

まずは全体の作業の流れを確認しておきます。

今回必要となる作業は次の通りです。

  • 1.ngrokを起動してWebhook用のURLを取得する
  • 2.TradingViewでストラテジーの設定を行い、Webhook経由のアラート通知を設定する
  • 3.PythonでWebhook通知を受信するシステムを構築する
  • 4.PythonでAPIを介して売買注文を出すプログラムを作成する
  • 5.3と4を組み合わせて自動売買システムを構築する

順番に解説していきます。

ngrokを起動してWebhook用のURLを取得する

まずはngrokを起動してWebhook用のURLを取得します。

ngrokを起動するにはターミナルで次のコマンドを実行します。



ngrok http 3000


3000はポート番号です。

起動すると次のような画面が表示されます。

起動画面

ForwardingにあるURL(赤枠部分)が外部に公開されているURLになります。

このURLをTradingViewのWebhook用のURLに設定すると、Webhook経由で通知を受けることが可能になります。

赤枠の部分はngrokを起動するたびに変更されるため、起動するたびに設定が必要になります。

TradingViewでストラテジーの設定を行い、Webhook経由のアラート通知を設定する

次にTradingViewの設定を行います。

売買ストラテジーの定義

ここでは例として、次の条件で自動売買システムを構築します。

MACDを利用したシンプルなトレード戦略です。

  • 1.通貨ペア:ドル円
  • 2.使用するテクニカル指標:MACD
  • 3.売買条件:ゴールデンクロスでロング、デッドクロスでショートでエントリー
  • 4.売買条件を満たすたびに、その時点で保有しているポジションは全てクローズする

ゴールデンクロスが発生したらロングでエントリー、デッドクロスが発生したらショートでエントリーします。

シグナルが発生したら、その時点で保有しているポジションは全てクローズします。

チャートの設定

次にTradingViewのチャートの設定を行います。

チャート画面を開き、USDJPY(ドル円)を選択します。

そしてIndicatorsボタンをクリックして、MACDを追加します。

Indicatorsボタンをクリックして、MACDを追加

検索ボックスでMACDと入れると、TECHNICALSの下にMoving Average Convergence DivergenceとMACD Strategyの2つが出てきます。

両方とも選択して画面を閉じます。

両方選択して画面を閉じます

これでMACDが表示されました。

MACDが表示

Moving Average Convergence Divergenceを選択すると、ローソク足チャートの下にMACDが表示されます。

MACD Strategyを選択すると、ローソク足チャートにゴールデンクロスとデッドクロスが発生したタイミングが書き込まれます。

青色でMacdLEと表記されているのがゴールデンクロス、赤色でMacdSEと表記されているのがデッドクロスです。

これでチャートの設定は完了です。

TradingViewを利用すればこのほかにもたくさんのインディケーターやStrategyを利用することができるので、独自戦略を簡単に作ることができます。

Webhook経由のアラート通知の設定

次にアラート通知の設定を行います。

アラートを設定するためには、チャート上のAlertをクリックします。

チャート上のAlertをクリック

ここでアラートの条件を指定することができます。

今回はMACDのゴールデンクロスとデッドクロスを利用するので、ConditionでMACD Strategryを選択します。

そして、Alert ActionsでWebhook URLを選択して、URLに先ほどngrokを起動した際に得られたURLを入力します。

この時、末尾に/webhookを加えます。

Messageで通知内容のフォーマットを指定することができます。

ここではデフォルトのまま先に進みます。

Createをクリックすると、アラートが登録されます。

Createをクリックすると、アラートが登録

アラートを設定すると、右側にある時計アイコンから確認することができます。

アラートを設定して、右側にある時計アイコンから確認

アイコンをクリックすると、設定されているアラートの一覧(画像青枠)とログ(画像オレンジ枠)を確認することができます。

アイコンをクリックすると、設定されているアラートの一覧(画像青枠)とログ(画像オレンジ枠)が表示

これでアラートの設定は完了です。

PythonでWebhook通知を受け取る仕組みを構築する

必要な設定が全て完了したので、ここからはPythonを使ってWebhook通知を受け取る仕組みを構築していきます。

PythonでWebhookを受信するためには、socketserverを使います。

これでポート番号を特定してWebhookを受信することができます。

そして、受信内容に応じて処理を実行するためには、http.serverのBaseHTTPRequestHandlerを使います。

BaseHTTPRequestHandlerを使えば、受信内容に応じて、処理を切り替えることができます。

次のコードでは、POSTリクエストを受信して、データの内容を表示してステータスコードとして200を返しています。



import http.server
import socketserver

class WebhookHandler(http.server.BaseHTTPRequestHandler):
    def do_POST(self):
        
        # データの抽出
        content_length = int(self.headers['content-length'])
        req_body = self.rfile.read(content_length).decode("utf-8")
        
        # 抽出したデータを表示
        print(req_body)
        
        # ステータスコード200を返す
        self.send_response(200)
        self.end_headers()
        
with socketserver.TCPServer(("", 3000), WebhookHandler) as httpd:
    httpd.serve_forever()


コードを実行すると、受信待ちの状態になります。

この状況で何かしらのPOSTリクエストを送るとデータを受信することができます。

テストとして適当なPOSTリクエストを送信してみます。



import requests
import time

url = "ngrokのURLを設定してください"

requests.post(url=url, json={"contents": "this is the test message"})


送信すると200が返ってきます。

そして先ほどのコードの結果を見ると、きちんとPOSTリクエストを受信して内容を表示できていることが確認できます。

POSTリクエストを受信して内容を表示

これでWebhookでPOSTリクエストを受信することができるようになりました。

APIを介して売買注文を出すPythonプログラムを作成する

次に、APIを介して売買注文を出すプログラムを作成します。

ここではfx_traderというクラスを定義して、売買注文や保有ポジションを確認する関数を加えました。

必要最低限の機能のみに絞っています。



from oandapyV20.endpoints import orders, positions
from oandapyV20 import API
import datetime


class fx_trader:
    def __init__(self, account_id, access_token, instrument="USD_JPY", environme
nt="practice"):
        # 変数定義
        self.instrument = instrument
        self.account_id = account_id
        self.access_token = access_token
        self.log = []
        
        # API用のクラスを定義
        self.client = API(access_token=access_token, environment=environment)
    
    def logging(self, text):
        logText = "[{}] {}".format(datetime.datetime.now().strftime("%Y/%m/%d %
H:%M:%S"), text)
        print(logText)
        self.log.append(logText)
        
        return
        
    def order(self, unit):
        # 売買注文の内容を設定
        self.data = {
          "order": {
            "units": unit,
            "instrument": self.instrument,
            "timeInForce": "FOK",
            "type": "MARKET",
            "positionFill": "DEFAULT"
          }
        }
        
        # 売買注文
        self.r = orders.OrderCreate(accountID=account_id, data=self.data)
        self.res = self.client.request(self.r)
        
        self.logging("new entry: {} at {}".format(unit, self.res.get("orderFillT
ransaction").get("price")))
        return
    
    def positions(self):
        # 保有ポジションを取得
        self.r = positions.PositionDetails(accountID=self.account_id, instrument
=self.instrument)
        self.res = self.client.request(self.r)
        
        # ロングとショートの保有数を抽出
        self.longPositionUnits = int(self.res.get("position").get("long").get("u
nits"))
        self.shortPositionUnits = int(self.res.get("position").get("short").get
("units"))
        
        # 結果を表示
        print("longPositionUnits", self.longPositionUnits)
        print("shortPositionUnits", self.shortPositionUnits)
        
        return
    
    def close(self):
        # ポジションをクローズ
        if self.longPositionUnits != 0:
            data = {"longUnits": "ALL"}
            self.r = positions.PositionClose(accountID=self.account_id, instrume
nt=self.instrument, data=data)
            self.res = self.client.request(self.r)
            
            self.logging("position close: {} at {}. pl: {}".format(
                fx.res.get("longOrderFillTransaction").get("units"),
                fx.res.get("longOrderFillTransaction").get("price"),
                fx.res.get("longOrderFillTransaction").get("pl"),
            ))
            
        if self.shortPositionUnits != 0:
            data = {"shortUnits": "ALL"}
            self.r = positions.PositionClose(accountID=self.account_id, instrume
nt=self.instrument, data=data)
            self.res = self.client.request(self.r)
            
            self.logging("position close: {} at {}. pl: {}".format(
                fx.res.get("shortOrderFillTransaction").get("units"),
                fx.res.get("shortOrderFillTransaction").get("price"),
                fx.res.get("shortOrderFillTransaction").get("pl"),
            ))
            
        return


APIで売買注文を出す方法については、こちらの記事で詳しく解説しています。

また、保有ポジションの確認やポジションを一括クローズする方法についてはこちらの記事で解説しております。

これでAPIを介した売買を行うためのPythonコードの準備が整いました。

参考記事:Pythonで「REST API」から売買注文を発注する方法を解説

参考記事:Pythonを使い「REST API」から通貨ペア別の損益状況を確認する方法について解説

3と4を組み合わせて自動売買システムを構築する

最後に、「3. PythonでWebhook通知を受け取る仕組みを構築する」と「4. APIを介して売買注文を出すPythonプログラムを作成する」を組み合わせ自動売買システムを構築していきます。

TradingViewから通知されるWebhook通知をPythonで受信して、内容に応じてfx_traderで売買注文やポジションのクローズなどを実装すれば自動売買が実現できます。

アラートの通知内容を確認

まずはアラートで受信するメッセージ内容を確認します。

TradingViewによるWebhook通知を受信すると、次のようなメッセージが表示されます。

アラートで受信するメッセージ内容を確認

アラートの設定で定義したMessageが受信されていることが確認できます。

このメッセージの内容に応じて売買注文をAPIを介して行うことができれば、自動売買が実現できます。

POSTリクエスト受信後に売買の処理を加える

次のコードでは、POSTリクエスト受信後に、内容に応じてfx_traderによる売買を行う処理を加えています。



import http.server
import socketserver


class WebhookHandler(http.server.BaseHTTPRequestHandler):
    def do_POST(self):
        # データの抽出
        content_length = int(self.headers['content-length'])
        req_body = self.rfile.read(content_length).decode("utf-8")
        
        # 保有ポジションのクローズ
        fx.positions()
        fx.close()
        
        # エントリー: 1ならロング、-1ならショートと判断できる
        flag = int(req_body.split(" ")[-1])
        fx.order(unit=unit*flag)
        
        # ステータスコード200を返す
        self.send_response(200)
        self.end_headers()

        
unit = 100
fx = fx_trader(instrument="USD_JPY", account_id=account_id, access_token=access_token)

with socketserver.TCPServer(("", 3000), WebhookHandler) as httpd:
    httpd.serve_forever()
    

上記のコードでは、POSTリクエストを受信したら、まずは保有ポジションを確認して全てクローズします。

その後にメッセージの内容に応じて売買注文を出します。

メッセージの最後は1か-1になっており、1ならゴールデンクロスを意味するのでロング、-1ならデッドクロスを意味するのでショートでエントリーします。

これで自動売買システムの完成です。

きちんと動作していることも確認できました。

動作していることを確認

TradingViewを利用すればさまざまなストラテジーが簡単に実装できる

以上のように、TradingViewとOANDAのAPIを組み合わせると、簡単に自動売買のシステムを構築することができます。

TradingViewを使えば、ストラテジーやインディケーターの実装が容易になります。

Pythonで実装が必要になるのはWebookのメッセージ内容に応じて売買処理を行う部分のみになるため、開発コストを大きく下げることができます。

ここでは売買戦略としてMACDを使ったシンプルなものを実装しましたが、TradingViewではアラート条件を簡単に変更することができるので、自由な投資戦略を簡単に実装することができます。

本記事の執筆者:TAT

               
本記事の執筆者:TAT 経歴
TAT2016年大学院卒業後、外資系IT企業に入社。
その後は金融情報→不動産テック→アドテク企業で、Pythonを用いたプロセスオートメーション、ダッシュボード開発、データ分析、AI開発などの業務に従事。
プログラミングや株式投資に関する情報を発信する「気ままなブログ」を運営中。

「REST API」をさらに学びたい方へオススメのコンテンツ

API

OANDA証券では、「REST API」に関する記事を豊富に提供しています。
「REST API」を利用するための手順、プログラミング言語の一つPythonを使い「REST API」を使用するまでの手順など、初心者の方向けコンテンツも豊富にあるので、APIを使った取引を始めてみたい方はぜひ参考にしてください。
ただしAPIを利用した取引は、OANDA証券の口座開設+いくつかの条件があります。
事前に確認を行い、ぜひOANDA証券の口座を開設し「REST API」を使った取引をご検討ください。


本ホームページに掲載されている事項は、投資判断の参考となる情報の提供を目的としたものであり、投資の勧誘を目的としたものではありません。投資方針、投資タイミング等は、ご自身の責任において判断してください。本サービスの情報に基づいて行った取引のいかなる損失についても、当社は一切の責を負いかねますのでご了承ください。また、当社は、当該情報の正確性および完全性を保証または約束するものでなく、今後、予告なしに内容を変更または廃止する場合があります。なお、当該情報の欠落・誤謬等につきましてもその責を負いかねますのでご了承ください。

この記事をシェアする

ホーム » APIの使い方 » TradingViewとOANDA証券の「API」を組み合わせた自動売買システムの構築方法