趣旨
TradingViewを見ていちいち取引所のサイトに移動して注文を出すのがだるい!という時に全部自動化してトレード放棄したいという邪な考えから作ったbotです。
同じことを全く別の方法で実現することも可能です。
Macでもラズパイでもレンタルサーバーでも実装できますが、実際に動かすとなるとレンタルサーバーでやるのが良いと思います。またサーバーで実装した場合はSmeeを使わなくて済むので簡単ですし、より安全です。
以下のコードを実行する場合は全て自己責任でお願い致します。
本記事は教育目的での共有であり、投資を勧誘するものではありません。
自動売買に必要なもの
- Smee
- TradingView有料アカウント
- Bitgetアカウント
- その他CEXアカウント(応用)
仮想環境設定
仮想環境のことをよく知らなくても念のためにやっておいた方が良いです。
python3 -m venv myenv
source myenv/bin/activate
専用のディレクトリを構築します。
mkdir tradingview
cd tradingview
SmeeとWebhook
Smeeとは
外部からのWebhookをローカルサーバーにデリバリーするサービスです。
SMEEをインストールします。
公式サイトに行けば必要なコマンドが記載されています。
公式サイトでランダムなプロキシーURLが表示されるので、以下のコマンドの「プロキシーURL」の部分をそのURLに書き換えてコマンドを打ちます。
smee -u https://smee.io/プロキシーURL -t http://127.0.0.1:5000/webhook
Smeeを使う理由
サーバーを外部に公開するのは危険だから。
Smeeを使えばローカルサーバーのままWebhookが使えます。
Webhookとは
Webhookが何か全くわからない場合はKintoneさんの記事を参照すると良いかもです。
簡単に言えば、イベント発生時にPOSTでデータを送信する機能です。
今回はTradingViewのWebhook機能を利用するので送信側の実装はやりません。
受信する側のみ実装します。
Flaskというフレームワークで簡易Webアプリを作ってそのアプリで受信するようにセットします。
コード(コピペ可)
では早速コードの準備に取り掛かります。
Flask設定
必要なライブラリをインストールします。
pip install Flask
pip install requests
Flaskのためのファイルを作成します。
touch flask.py
以下のコードをflask.pyにコピペします。
from flask import Flask, request
import json
import subprocess
app = Flask(__name__)
@app.route('/webhook', methods=['POST'])
def handle_webhook():
try:
data = request.json
strategy = data.get("strategy")
if strategy == "bitget":
side = data.get("side")
symbol = data.get("symbol")
amount = data.get("amount")
subprocess.run(["python", "bitget.py", "--side", side, "--symbol", symbol, "--amount", amount])
elif strategy == "okx":
side = data.get("side")
symbol = data.get("symbol")
amount = data.get("amount")
subprocess.run(["python", "bybit.py", "--side", side, "--symbol", symbol, "--amount", amount])
else:
# raise an exception if strategy is not recognized
raise ValueError("Invalid strategy")
return "OK"
except Exception as e:
# log the error message
app.logger.error(f"Error: {str(e)}")
# return an error response to the client
return {"error": str(e)}, 400
if __name__ == '__main__':
app.run()
CCXT設定
ccxtは複数の取引所のAPI接続を簡単にするためのライブラリです。
これがなかったら全ての取引所のAPIドキュメントを全て読み込んで設定しないといけなくなるので作業量がかなり増えてしまいます。
ccxtをインストールします。
install ccxt
bitget.pyを作成します。
touch bitget.py
bitget.pyに以下のコードをコピペします。
import ccxt
import argparse
import config
parser = argparse.ArgumentParser()
parser.add_argument("--side", help="Trade side (buy or sell)", choices=["buy", "sell"])
parser.add_argument("--symbol", help="Symbol")
parser.add_argument("--amount", help="Amount")
args = parser.parse_args()
side = args.side.lower()
symbol = args.symbol.upper()
amount = float(args.amount)
bitget_exchange = ccxt.bitget({
"apiKey": config.bitget_api_key,
"secret": config.bitget_secret_key,
"password": config.bitget_password,
"enableRateLimit": True
})
bitget_exchange.options["defaultType"] = "future"
try:
positions = bitget_exchange.fetch_positions(symbol)
except ccxt.BaseError as e:
print(f"Error fetching positions: {e}")
exit(1)
has_long_position = False
has_short_position = False
for position in positions:
if position['info']['symbol'] == symbol:
if position['info']['holdSide'] == 'long' and float(position['info']['available']) > 0:
has_long_position = True
elif position['info']['holdSide'] == 'short' and float(position['info']['available']) > 0:
has_short_position = True
if (side == "buy" and has_short_position) or (side == "sell" and has_long_position):
bitget_exchange.create_order(symbol, "market", side, amount, params={"reduceOnly": True})
bitget_exchange.create_order(symbol, "market", side, amount)
else:
bitget_exchange.create_order(symbol, "market", side, amount)
Config設定
config.pyを作成します。
touch config.py
config.pyに以下の内容をコピぺして、該当する情報をダブルクオーテンションの中に記載します。
bitget_api_key = ""
bitget_secret_key = ""
bitget_password = ""
APIキーを直に書いて保存しているのでセキュリティに問題があるかも知れません。気になる方は暗号化の方法を学んでご自身で暗号化してください。
あとはSmeeが起動しているのを確認してbotを起動します。
python flask.py
Smeeの起動確認は以下のコマンドで出来ます。
sudo systemctl status smee.service
TradingViewのアラート
以下はサンプルです。
銘柄に応じてDOGEUSDT_UMCBLのDOGEの部分を別の銘柄に変更します。
{"strategy":"bitget","side":"{{strategy.order.action}}","symbol":"DOGEUSDT_UMCBL","amount":"{{strategy.order.contracts}}"}
次にWebhookのURLの箇所にSmeeのプロキシーURLをセットします。
プロキシーURLはSmeeのページを訪れた時に付与されるURLです。
おまけ
例として既存のストラテジーをアレンジして作ったオリジナルストラテジーのコードを記載します。
BTCの日足に対して適用させると以下のような結果になります。
以下のPineScriptコードをTradingViewでコピペすると使えます。
//@version=4
strategy("danieltanaka", overlay=true)
len = input(14, minval=1, title="DI Length")
lensig = input(14, title="ADX Smoothing", minval=1, maxval=50)
up = change(high)
down = -change(low)
plusDM = na(up) ? na : (up > down and up > 0 ? up : 0)
minusDM = na(down) ? na : (down > up and down > 0 ? down : 0)
trur = rma(tr, len)
plus = fixnan(100 * rma(plusDM, len) / trur)
minus = fixnan(100 * rma(minusDM, len) / trur)
sum = plus + minus
adx = 100 * rma(abs(plus - minus) / (sum == 0 ? 1 : sum), lensig)
DMX = (adx/25)*(plus-minus)
longCondition = crossover(DMX, 0)
if (longCondition)
strategy.entry("Long", strategy.long)
shortCondition = crossunder(DMX, 0)
if (shortCondition)
strategy.entry("Short", strategy.short)
plot(DMX, color=#d0b170, style=plot.style_area, transp=40, title="DMX")
plot(plus, color=color.green, title="+DI")
plot(minus, color=color.red, title="-DI")