スロースキャボット 「招き猫」 manekineko.py

BitcoinBot「招き猫」目次に戻る

「招き猫」ちゃんの戦略

  1. 2分前の価格と現在を比較。ある程度のブレイクで↑か↓かを決める。
  2. ポジションを持つ。
  3. 利益は伸ばし続ける。
    例:902000でトレイリングモードに入り、902300(勿論、幅は変更可能)で再度トレイリングに入るということを繰り返す。
    この技を「ローリングトレイリング」と名づけた2020/1/13。
    (ryota-trade.com見返したら同じロジックが書いてあった。随分前に見てたはず?だが?意識になかった。盗作はこうして生まれるのだろう)
  4. BFはスプレッドが100円幅くらいあるので無駄に売買しない。
  5. トレイリング以前の損は即カット。
  6. はじめに戻る

設定は難しいが、損切幅を小さくすると損切しかしなくなるので、利確幅を小さくするほうが良いと思う。

どんな戦略も、取引所の中でのトレードであれば、勝つのは困難に決まっている。

招き猫の場合、まずは約定時のスプレッドに打ち勝たなければならない。


ソースコード

config.json #keyとsecretを隠しておくファイル
parameter.json #各種パラメーターを格納しておくファイル
config.py #keyとsecretを読み込むだけのプログラム
parameter.py #パラメータを読み込むだけのプログラム

設定ファイルはこちらと同じ key&secret、パラメーターはクラスで管理

本体ファイルは以下

#!/usr/bin/python3
# -*- coding: utf-8 -*-

#last update 2020/1/3 23:00


from pprint import pprint #辞書を整形出力
import time #タイマーとか現在時刻とか
import pybitflyer #ラッパー
from config import Config #Config()クラスを読み込む,api_key & api_secretをコードに書かない
from parameter import Parameter #パラメーター類はコードと別にしておく
import json #データ形式
import requests #APIリクエスト
import datetime #日時ライブラリー

#インスタンス化おまとめ
cfg = Config() #keyとsecretを読み込み、クラスで__init__する
p=Parameter() #パラメーターの読み込み、同上
#pprint(vars(p)) #pの変数一覧出力「関数vars()]
#ラッパーpybitflyerのインスタンス化
api = pybitflyer.API(api_key=cfg.api_key, api_secret=cfg.api_secret)
#グローバル変数
direction=True
mini2=120 #比較する時間(mini2 秒前)
p.profit_width=2000 #テスト用利確する金額(円)



#思わぬ事態を防ぐため、安全のための初期化、いずれなくす
def get_started():
    p.product_code="FX_BTC_JPY"
    p.lotsize= 0.01
    p.side= "",
    p.child_order_type= "MARKET"
    p.temp_price= 798000.0
    p.current_price=  798000.0
    p.past_price=  798000.0
    p.profit_width= 500
    p.stop_width= -2000 #成績に一番影響があるのはこれ、最適値を見つけるのだ

    p.posi_side=  ""
    p.posi_minus= -1.0
    p.posi_open_price=  798000.0
    p.posi_pnl=  1.0
    p.posi_lotsize=  0.0
    p.posi_require_collateral=  2020.8475
    p.posi_product_code=  "FX_BTC_JPY"
    p.posi_sfd=0.0

    p.trail_count=0
    p.trail_start_price=  798000.0
    p.trail_stage=  0
    p.trail_pnl=  0.0
    p.trail_profit_width=300.0
    p.trail_stop_width=  -800.0 

def get_ticker():#値段を取得する関数
    response=requests.get('https://api.bitflyer.com/v1/getticker?product_code=FX_BTC_JPY').json()
    #response = api.ticker(product_code=p.product_code)
    p.current_price=response['ltp']
    #print('   Current price= ',p.current_price)
    return response['ltp']

def pypy_getpositions():#持っているポジションを変数に格納する
    try:
        response = api.getpositions(product_code=p.product_code)
        if response: #ポジを持っていれば
            p.posi_product_code=response[0]['product_code']
            p.posi_sfd=response[0]['sfd']
            p.posi_lotsize=response[0]['size']
            p.posi_pnl=response[0]['pnl']
            p.posi_side=response[0]['side']
            p.posi_open_price=response[0]['price']
            p.posi_require_collateral=response[0]['require_collateral']
            if response[0]['size']<0.01:
                if response[0]['size'] == 0:
                   p.posi_lotsize=0
                else:
                   p.posi_lotsize=0.01
            else:
                 pass
            if response[0]['side']=='SELL':
                p.posi_minus=-1
                p.side="BUY"
            else:
                p.posi_minus=1
                p.side="SELL"
            return( response[0])
        else:
            print('response=False',response)
            print('建玉はありません\n')
            return(False)
    except:
        pass

def pypy_sendchildorder():#売買する関数
    try:
        response = api.sendchildorder(
                   product_code=p.product_code,
                   child_order_type=p.child_order_type,
                   side=p.side,
                   size=p.posi_lotsize)
        print( '  childorderを受け付けました。 ',response)
        p.child_order_acceptance_id=response[child_order_acceptance_id]
        return response
    except:
        pass

'''---------------------------------------------------------------'''
def new_entry(tick1,tick2): #新規エントリー
    print('新規に玉をエントリーします')
    if tick1-tick2>0: #上昇
        p.side='BUY'
        print('新規エントリー:BUY long 上昇基調',p.product_code,p.current_price,
                                                p.lotsize,p.side)
    else: #下降中
        p.side='SELL'
        print('新規エントリー:SELL short 下落基調',p.product_code,p.current_price,
                                                  p.lotsize,p.side)
    try:
        response = api.sendchildorder(
                   product_code=p.product_code,
                   child_order_type=p.child_order_type,
                   side=p.side,
                   size=p.lotsize)
        print( '  新規childorderを受け付けました。 ',response)
        p.child_order_acceptance_id=response[child_order_acceptance_id]
        return response
    except:
        pass
'''---------------------------------------------------------------'''
def judgement(tick1,tick2): #決済関数
    #print ('\n  -----  judgement ---')
    posi_profit_width=(tick1 - p.posi_open_price)*p.posi_minus#現価-posi_open=含み損益幅
    posi_profit=posi_profit_width * p.posi_lotsize#含み損益額
    print('posi_profit_width {:.0f}  posi_profit  {:.2f}   '.format(posi_profit_width,posi_profit),end='')
    #決済するかどうか
    if posi_profit_width> p.profit_width:#決済水準に達している
        print('    posi_profit_width {:.0f}  p.profit_width   {:.2f}   '.format(posi_profit_width, p.profit_width))
        print('    おめでとうございます、儲かってます    ',posi_profit)
        p.trail_start_price = tick1
        status_print()
        print('   judgement --->  trailling ) ')
        trailling(tick1,tick2)
    elif posi_profit_width < p.stop_width:#損切水準だ
        print('posi_profit_width  p.stop_width',posi_profit_width,p.stop_width)
        print('{}損切執行--必要経費じゃ'.format(posi_profit))
        print('call pypy_sendchildorder')
        status_print()
        print('    judgement -> sendchildorder(stop)  ')
        pypy_sendchildorder()
    else:
        pass
'''---------------------------------------------------------------'''

def trailling(tick1,tick2):#肝関数トレーリング
    print ('\n  -----  trailling ---')
    p.trail_count +=1 #何段目のトレールかを知る
    print('     p.trail_count = {} p.trail_stage= {} '.format(p.trail_count,p.trail_stage))

    trail_profit_width=(tick1 - p.trail_start_price)*p.posi_minus
    p.trail_pnl=trail_profit_width*p.posi_lotsize
    if trail_profit_width>p.trail_profit_width:#再trailling
        print('    trail_profit_width{} p.trail_profit_width{}  '.format(trail_profit_width,p.trail_profit_width))
        print('    儲けはtrailling pnl {}. もっと行きます'.format(p.trail_pnl))
        p.trail_start_price = tick1#再度トレイルスタート
        p.trail_stage+=1#何段目のトレイルかのカウント
        status_print()
        time.sleep(10)
    elif trail_profit_width  p.trail_stop_width:#マイナス幅がstop幅より大きくなればtrail_stop
        print('    trail_profit_width {}  p.trail_stop_width {}  '.format(trail_profit_width , p.trail_stop_width))
        print('  反転かもな、一旦利食いじゃ - send child order ')
        print('call pypy_sendchildorder')
        status_print()
        pypy_sendchildorder()
        p.posi_lotsize=0
        p.trail_count=0
    else:
         pass
         print('  様子見だ (pass) ')
'''---------------------------------------------------------------'''
def main():
    count=0 #繰り返しのカウント
    tick=[] #現在価格をためておく
    p.interval=3 #3秒に一回処理をする
    a=int(mini2/p.interval)#mini2分(今は2分)は何カウントか
    get_started()#初期化
    while True: #永久ループ
        tick.append(get_ticker())#tick[]に価格情報を貯蓄
        print('\n  {} s  price {:.0f}  side={}'.format( count*p.interval,tick[-1],p.posi_side),end='')
        p.posi_pnl=(tick[-1]-p.posi_open_price)*p.posi_lotsize#*p.posi_minus#利益幅
        if count*p.interval > mini2:#開始後2分以上経っていたら
            #main 処理部
            posi=pypy_getpositions()#True ポジ有り False ポジ無しreturn(result[0])
            if posi==False:#ポジがなかったら
                p.current_price=tick[-1]
                status_print()
                print('  main -> new_entry()')
                new_entry(tick[-1],tick[-a])#新規ポジションオーダー
            else:#判定関数へ
                if p.trail_count==0:#trail中でなければjudgementへ
                    print('    main -> judgement() ',end='')
                    judgement(tick[-1],tick[-a])#判定関数に飛ぶ
                else :#trail中であれば
                    status_print()
                    print('main -> trailling()  ')
                    trailling(tick[-1],tick[-a])#trail関数へ
        count+=1
        time.sleep(p.interval)

if __name__ == '__main__':
   main()

パクった(参考にした)特定のbotはない。ソースはオリジナル。
(なぜなら他人のボットのソースはまだ読めない。解らないことだらけだ)
結構バグが出て手直しをしたので、汚いソース。
変数値確認のprint文がそのまま入ってる(又使うだろうから)

↓コンソールの出力例

損は早く小さく切り、プラスの場合利益を伸ばして利確する猫なので、ログの表示はマイナス表示が多い。
心理的に焦るが、胆力じゃ。ニャンリョクじゃにゃん。

まずは2分間カウントしながら価格データを蓄積します 
 108s  903455 yen  side=
  111s  903627 yen  side=
  114s  903620 yen  side=
  117s  903568 yen  side=
  120s  903513 yen  side=
  123s  903353 yen  side=

含み益が出たらトレイリングモードに入って再帰的に価格を伸ばし、反転したら決済する。
  192s  902835 yen  side=SELL    main --- judgement  posi_profit  479  posi_profit  4.79   
  195s  902838 yen  side=SELL    main --- judgement  posi_profit  476  posi_profit  4.76   
  198s  902812 yen  side=SELL    main --- judgement  posi_profit  502  posi_profit  5.02       posi_profit 502  p.profit 500.00   
    おめでとうございます、儲かってます     5.0200000000000005
  201s  902866 yen  side=SELLp.lotsize= 0.01
p.side=p.side= BUY
p.child_order_type= MARKET
p.current_price= 902866.0
p.profit_width= 500
p.stop_width= -500
p.posi_side= SELL
p.posi_minus= -1
p.posi_open_price= 903314.0
p.posi_pnl= 0.42449858
p.posi_lotsize= 0.01
p.trail_count= 1
p.trail_stage= 0
p.trail_start_price= 902812.0
p.trail_pnl= -0.0
p.trail_profit_width= 300.0
p.trail_stop_width= -800.0
  main -> trailling  
  -----  trailling ---
     p.trail_count = 2 p.trail_stage= 0 
 -- 様子見だ (pass) --

  -----  trailling ---
     p.trail_count = 101 p.trail_stage= 0 
    trail_profit_width -920.0  p.trail_stop_width -800.0  
----  反転かもな、一旦利食いじゃ - send child order  --

  childorderを受け付けました。  {'child_order_acceptance_id': 'JRF20200113-015608-543805'}

  501s  903900 yen  side=SELLresponse=False []
建玉はありません

  main -> new_entry()
新規に玉をエントリーします
新規エントリー:BUY long 上昇基調 FX_BTC_JPY 903900.0 0.01 BUY
  新規childorderを受け付けました。  {'child_order_acceptance_id': 'JRF20200113-015611-210872'}


一方、含み損が出たらすぐに決済する
    main -- judgement  posi_profit  -614  posi_profit  -6.14   posi_profit_width>p.stop_width True
-6.140000000000001損切執行--必要経費じゃ
call pypy_sendchildorder

文系Fラン卒、非IT企業で営業職の、子持ち(ニートと大学生)

そんなおいらが独学で作ったプログラムなので、誰かダメ出ししてくれたら嬉しい。

関数のクラス化とかした方が良いのかもしれないが、まだよくわからない。


その後プログラムは改変を繰り返しバージョン40くらいになっているが、ソースコードはぐちゃぐちゃで、自分でも意味不明になっており、公開はできない。
勝率自体は最初と一緒で、スプレッドの分だけ少しづつ負けていく感じ。
2020年5月頃、BitFlyerのSFD多発のタイミングで動作を停止し、他の取引所への移転もままならず現在に至る。BFはBOT運用的には簡単と言える。

BitcoinBot「招き猫」目次に戻る

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