「招き猫」ちゃんの戦略
- 2分前の価格と現在を比較。ある程度のブレイクで↑か↓かを決める。
- ポジションを持つ。
- 利益は伸ばし続ける。
例:902000でトレイリングモードに入り、902300(勿論、幅は変更可能)で再度トレイリングに入るということを繰り返す。
この技を「ローリングトレイリング」と名づけた2020/1/13。
(ryota-trade.com見返したら同じロジックが書いてあった。随分前に見てたはず?だが?意識になかった。盗作はこうして生まれるのだろう) - BFはスプレッドが100円幅くらいあるので無駄に売買しない。
- トレイリング以前の損は即カット。
- はじめに戻る
設定は難しいが、損切幅を小さくすると損切しかしなくなるので、利確幅を小さくするほうが良いと思う。
どんな戦略も、取引所の中でのトレードであれば、勝つのは困難に決まっている。
招き猫の場合、まずは約定時のスプレッドに打ち勝たなければならない。
ソースコード
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運用的には簡単と言える。