「招き猫」ちゃんの戦略
- 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運用的には簡単と言える。