こんにちは、mabuiです。
今回はcryptwatchから取得した情報でemaを計算して、
BitMEXで自動売買する、簡単なロジックのプログラムを作成しました。
まずは今回ロジックに使用したemaを説明していきます。
ソースコードは本文下記に公開しています。
emaとは
ema 指数平滑移動平均線(= Exponential Moving Average)
sma(単純移動平均線、またはma(移動平均線))の場合、期間内の足の終値を平均したものを
繋いで平均線として表示しますが、emaは直近の価格に比重がかかるため、
よりトレンドの転換が早く見極められますが、騙しにも引っかかりやすくなります。
上の図はBitMEXのBTC/USD 4時間足チャートです。
ロウソク足の下にある赤い線がemaで、青い線がsma(ma)です。
emaがsmaと比較して、値動きに追従しているのがわかります。
なぜ移動平均線をトレードに使用するか?
移動平均線とは一定期間の取引でついた価格の平均を表す線です。
ということは現在値が移動平均線の上にある場合、
かつ市場参加者のごく少数が極端な量のポジションを持っていない場合は、
買いでポジションを取っているトレーナーの半数以上は含み益を持っている
ということになります。
それらのトレーナーの心理状況としては、利が乗っているのでもちろん強気です。
人によっては買い増しも検討しているでしょう。
逆に現在値が移動平均線を下回ると、半数以上のトレーナーは損が出始めるため
急激に弱気になります。
これを市場参加者の特徴に合わせて使用するとより有用になります。
例えば、数日前の大きなニュースで値が上がった銘柄には5日移動平均線が有効でしょう。
直近5日間の市場参加者が多いことが見込まれるからです。
この場合現在値が5日移動平均線を割り込むとほとんどの参加者が弱気になるため、
その直後に値ががくんと下がる可能性が高いです。
少し話題がずれましたが、下記でプログラムの動作説明をします。
動作
- 分足10分間でemaを計算して、
その価格を現在値が超えた場合にエントリーを仕掛けます。 -
エントリー後は設定した利確幅、
または損切り幅に到達したらポジションをクローズします。 -
エントリーの指値が刺さらなかった場合は、
約1分後に注文をキャンセルします。
上記3つの動作を10秒間隔で延々とループします。
そのため、利確後も現在値がemaを超えていたら再度エントリーを仕掛けてしまうのが
現状イケてない点ですw
利益を継続的に上げるほどの完成度には至っていないので、参考程度に活用下さい。
ソースコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
#!/usr/bin/python3 import requests import json from datetime import datetime, timedelta import pandas as pd import time import ccxt import sys LOT = 100 CLOSE_RANGE = 30 STOP_RANGE = 20 # api・シークレットキーを記入 bitmex = ccxt.bitmex({ 'apiKey': 'xxxxxxxxxx', 'secret': 'xxxxxxxxxx', }) # testnetで使用する場合は下記コメントアウトを外す # bitmex.urls['api'] = bitmex.urls['test'] def limit(side, price, size): return bitmex.create_order('BTC/USD', type='limit', side=side, price=price, amount=size) def market(side, size): return bitmex.create_order('BTC/USD', type='market', side=side, amount=size) # dataframe for executions df = pd.DataFrame(columns=['exectime', 'open', 'high', 'low', 'close', 'price', 'volume']) #ローソク足の時間を指定 periods = ["60"] # after以降のデータを取得(after = 10分前) after = (datetime.now() - timedelta(minutes=10)).strftime('%s') #クエリパラメータを指定 query = {"periods":','.join(periods)} query['after'] = ''.join(after) def get_ema(): #ローソク足取得 result = json.loads(requests.get("https://api.cryptowat.ch/markets/bitmex/btcusd-perpetual-futures/ohlc",params=query).text)["result"] # add to dataframe for period in periods: row = result[period] df = pd.DataFrame(row, columns=['exectime', 'open', 'high', 'low', 'close', 'price', 'volume']) # 平滑化係数(0~1を指定、1に近いほど現在の価格比重が重くなる) alpha = 0.15 # emaの計算 ※pandasバージョン0.18.0以上 ema = df['close'].ewm(alpha=alpha).mean()[-1:] # print("ema: %s" % ema) return ema entryPrice = 0 openId = '' closeId = '' # while while True: try: print("==========") print("entryPrice: " + str(entryPrice)) print("openId: " + str(openId)) print("closeId: " + str(closeId)) last = bitmex.fetch_ticker('BTC/USD')['last'] print('last price: ' + str(last)) open_orders = bitmex.fetch_open_orders() position = bitmex.private_get_position() # if Active Orderがない場合 if open_orders == []: # if ポジションを持っていない場合 if position == [] or position[0]['currentQty'] == 0: print('No Position') ema = get_ema().values[0] print("ema: " + str(ema)) # if 最後の約定価格がemaより高い if last >= ema: # 買いポジションでエントリー entryPrice = last - 2 order = limit('buy', entryPrice, LOT) print("buy entry") openId = order['id'] # elif 買いポジションを持っている場合 elif position[0]['currentQty'] >= LOT: # エントリーポイント + CLOSE_RANGE で指値 order = limit('sell', entryPrice + CLOSE_RANGE, LOT) print('position close') closeId = order['id'] # if エントリーポイント - STOP_RANGE なら損切り if position[0]['currentQty'] >= LOT and last <= (entryPrice - STOP_RANGE): market('sell', LOT) print('loss cut') order = bitmex.cancel_order(closeId) print('order cancel') # if エントリー注文を出して1分以上経過した場合、注文を取り消す if open_orders != [] and open_orders[0]['id'] == openId and datetime.now() - timedelta(minutes=1) > datetime.fromtimestamp(int(str(open_orders[0]['timestamp'])[0:10])): cancel = bitmex.cancel_order(openId) print("order cancel") except Exception as e: print("error: {0}".format(e)) time.sleep(10) |
githubのソースコードはこちら