脳死BOT

import ccxt
import datetime
import json
import logging
import time
from random import random

### 準備
# ログ
logger = logging.getLogger(__name__) # %(name)sになる
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s-%(message)s')

# 標準出力
streamHandler = logging.StreamHandler()
streamHandler.setFormatter(formatter)

# ロガーにハンドラーを追加
logger.addHandler(streamHandler)

# ログイン周りの処理
bm_keys_json = open('config/mexkeys.json', 'r')
bm_key = json.load(bm_keys_json)
bitmex = ccxt.bitmex(bm_key)

### パラメータ
# ccxt関連
symbol = 'BTC/USD'
type = 'market'
side = 'buy'
amount = 1.0
price = None
params = {}

# ログ出力条件用変数
last_stopPx = 0
loop_count = 0

# 取引条件設定
diff_triger = 5
offset_percent = 1
size_percent = 5
min_size = 1.0
loop_second = 60

### 関数
def make_position(side, order_amount):
   type = 'market'
   price = None
   params = {}
   order = bitmex.create_order(symbol, type, side, order_amount, price, params)
   logger.info("merket order is done. id:" + order['id'])

def make_trailstop(side):
   type = 'stop'
   reversed_side = 'sell' if side == 'buy' else 'buy'
   amount = None
   price = None
   lastPrice = bitmex.fetch_ticker(symbol)['last']
   # 0.5刻みじゃないとエラーになるので、1単位まで丸める
   offset = (-1.0 if side == 'buy' else 1.0 ) * round(offset_percent / 100.0 * lastPrice)
   stopPx = lastPrice + offset
   params = {
       'stopPx': stopPx,
       'pegPriceType': 'TrailingStopPeg',
       'pegOffsetValue': offset,
   }
   order = bitmex.create_order(symbol, type, reversed_side, amount, price, params)
   logger.info("trailing stop order is done. id:" + order['id'])

def cancel_orders(orders):
   for order in orders:
       bitmex.cancel_order(order['id'])
       logger.info("order id:" + order['id'] + "is cancelled.")

### 処理開始
logger.info("=====GO AHEAD, BRAIN-DEAD BOT=====")
while True:
   try:
       # アクティブな注文の取得
       orders = bitmex.fetch_open_orders()
       # 現在の所持数を取得
       balance = bitmex.fetch_balance()['BTC']['total']
       balance_used = bitmex.fetch_balance()['BTC']['used']
       position = bitmex.private_get_position()[0]['currentQty']

       ## 注文がない場合
       if len(orders) == 0:
           # 注文数を算出
           order_amount = balance * size_percent / 100.0
           order_amount = order_amount if order_amount >= min_size else min_size

           # 買いか売りかを決定
           side = 'buy' if random() > 0.5 else 'sell'
           logger.info("Create ORDER..." + side + ":" + str(order_amount))
           ## ポジションがない場合は注文とトレールストップを出す
           if position == 0:
               make_position(side, order_amount)
               make_trailstop(side)
           
           ## ポジションだけがある場合、ストップを出す
           else:
               side = 'buy' if position > 0 else 'sell'
               make_trailstop(side)
               
       ## 注文がある場合
       else:
           ## ポジションがない(成立しなかった)場合、キャンセルする
           if balance_used == 0:
               cancel_orders(orders)
           
           ## ポジションがある場合
           else:
               if orders[0]['type'] == 'stop':
                   # 変化があればログを出力する
                   stopPx = str(orders[0]['info']['stopPx'])
                   # 流石にログが出力されなさすぎて不安なのでちょっとは出す
                   loop_count = loop_count + 1
                   if last_stopPx != stopPx or loop_count > 100:
                       loop_count = 0
                       last_stopPx = stopPx
                       logger.info('Current stopPx is ' + stopPx)
               else:
                   cancel_orders(orders)

   except Exception as x:
       logger.info(x)

   finally:
       time.sleep(loop_second)

この記事が気に入ったらサポートをしてみませんか?