目次。
この文章を読んで、面白い!役に立った!...と思った分だけ、投げ銭していただけると嬉しいです。
【宣伝】ギターも歌も下手だけど、弾き語りをやっているので、よければ聴いてください。
はじめに。
株式自動売買プログラム開発関連の文章は、以下のカテゴリーにまとめているので、興味のある方はどうぞ。
前回は、『過去と失敗談と上場企業全ての中間・期末配当情報を収集するプログラムを書いた話。』をした。
この後も配当情報を使って、何かしらの株式売買アルゴリズムができなかと、色々とデータをいじくっていたが、行き詰ってしまったので、しばらく放置。
今回は、スイングトレードしつつも、時々、デイトレードをしてみようという話。
コロナショック(株価大暴落)。
今回の話とは、直接的な関係はないが、何となくコロナショックの話を挿もうと思う。
ご存知の人も多いと思うが、新型コロナウイルスの影響で2020年2月~3月の株価は、大暴落した。すでに株式の自動売買プログラムの開発は行っていたが、その頃、僕が実際やっていた株式売買は、主に裁量取引(アルゴリズムを使わない人による取引)。
僕も他の人と同様に損切がなかなかできない。コロナショック以前からずっと含み損を抱え続けていて、いくつかの銘柄は何か月も塩漬けになっていた。「株の塩漬け」は、一番やってはダメなこと。ダメだと分かっていながら、なかなか損切することができなかった。そして、そもそも僕が株式市場に投下しているお金はしばらくの間、手元に必要ないものなので、株式を塩漬けする癖を直そうという強い動機もなかった。値下がりしていても、2~3年あれば、下がっている株価は上がるから、大丈夫だろうと思っていた。言うまでもないが、株式を2~3年、塩漬けしているようでは、株式市場では儲けることはできない。
そんな中、やってきたコロナショック。今までの含み損に加えて、新たに30万円の損失を被ることになった。もっと早く損切すれば、抑えられた損失である。けれども、損切することができずに新たに塩漬け株を増やしてしまった。
先ほども言った通り、株式市場に投下しているお金は、別に今すぐ必要なお金ではない。いくら含み損が膨らもうと、また2~3年くらいほっておけば、いつか株価が値上がりするだろう…なんて思おうとしたが、思えなかった。「株式売買を〇年間やって、トータルの損益は、±0円です」だなんて、いくら何でもアホ過ぎないか?
さらに、コロナショックによる株価の大暴落後、なんと4月から株価が急上昇し始めた。「この急上昇を逃すわけにはいかない!」と思い、ちゃんと塩漬けになっている株式に向き合い始めた。
まずは、塩漬けになっている銘柄をさっさと売り払って、利益が出そうな銘柄を買った。損切をきちんとして、売買の回数をできるだけ増やす、つまり資金の回転をできるだけ速くすることを意識した。また、コロナ自粛で研究室に行けなかったので、株式自動売買プログラム開発もどんどんと進めた。
そして、コロナショックで失った30万円は、すべて取り戻すことができた。
コロナショックによる株価の大暴落→株価の急回復による僕の株式の収益は、±0円である。お金の面から考えると、損も得もしていないが、僕は、お金以外の面で2つの得をした。
1つ目は、「損切の経験」。今まで含み損から目を背けて、出来る限り損切をせずに株式を売買していた。しかし、このコロナショックでそうは言っていられなくなり、膨らんだ含み損の処理を始めた。このコロナショックで未だかつてないほど、たくさんの損切を行った。損切をしまくったおかげで、損切に対する抵抗感が少なくなり、積極的に損切ができるようになった。
2つ目は、「株式自動売買プログラム開発の進展」。さっき言った通り、新型コロナウイルスの影響で、大学に立ち入ることができなくなったので、株式自動売買プログラムの開発をどんどん進めて、コロナショック以降の購入株式の銘柄選びは、この開発したプログラムの出力結果を参考にして行うようになった。
スイングトレードとデイトレード。
スイングトレードは、ある日に株式を買って、その数日後に売って利益を得るというトレード方法。一方で、デイトレードは、ある日に株式を買って、その日に売って利益を得るというトレード方法。前者と後者の違いは、株式の保有期間。スイングトレードは、平均して数日間、株式を保有しておくのに対し、デイトレードの平均株式保有期間は、1日にも満たない。
株式保有期間を長くすれば長くするほど、企業の業績とか、経済状況といった株価チャートから読み取れない要因によって株価が変動する。株価チャートベースのアルゴリズムの精度を上げるためには、これらの影響を少なくするために株式の保有期間を短くする必要がある。しかし短くし過ぎる(デイトレード)と、一日に大量の株価データを取ってこなければならなくなる。そうなると、計算が重くなるとか、証券会社に大量のアクセスをしなければいけないとかいった新たな問題が生じてしまう。そのため、僕は、スイングトレードをやっているのである。
と言いつつも、保有している株式全ての評価額は、1日で数千円くらい変動する。毎回、この株価の変動に対して、何もしていなかったのだが、どうももったいない。スイングトレードで株式を数日間保有しておくだけではなく、どうにかしてその数日間の間にこの変動を上手く使って、利益を得られないだろうか?
まずはデイトレードのプログラムをふんわりと考えてみた。
板情報を取得。
板っていうのは、ある銘柄に対して行われている買注文と売注文が確認できるもの。この板を見て、売注文が買注文よりもたくさんあれば、その銘柄を売りたがっている人がたくさんいるということを表していて、供給が需要よりも多いので、株価が下がるであろうということが予想できる。逆もしかり。
まずは板情報を取ってきて、売りの優勢度合を次のように定義してみた。
(...分数の横線の長さが上手くいかん...)
買・売注文が現在の株価から離れるに従って、影響が少なくなるようになっている。
売りの優勢度合いが高いときに株式を売って、優勢度合が買いに逆転したら、売った株式を買い戻そうという魂胆。
日経平均株価を元に。
板情報は、どちらかというと「次の瞬間、株価は上がるか?下がるか?」を判断するのには、いい情報であるが、これだとさすがに局所的すぎる。できれば、1日のうちに株価が高いところで株式を売って、低いところで株式を買い戻したい。
というわけで、日経平均株価の株価チャートも売買判断に加味することにした。さっきまで板情報の話をしていたが、多分、こっちの情報をメインの指標にして、板情報をサブの情報にした方がいいのかもしれない。
使っているデータは、5分足。25分移動平均線と125分移動平均線を使って、売買タイミングを決める。そして、移動平均線に加えて、5分足の株価チャートの極大と極小も売買タイミングを判断する材料に加えている。
ソースコード(プログラムコード)。
import XXXXX import numpy as np import datetime import os import glob import time import requests from bs4 import BeautifulSoup import re request_header = {'header'} SessionID, cookie_jar = XXXXX.getSessionID() def get_sell_to_buy(stock_code): order_book = np.zeros((2, 10, 2)) r = requests.get(url, request_header, cookies=cookie_jar) soup = BeautifulSoup(r.text, "html.parser") table_2 = soup.findAll('table') #板情報を取ってくるコード。 selling_trend = 0 buying_trend = 0 for i in range(10): selling_trend += order_book[0][i][1]/(order_book[0][i][0]-order_book[0][0][0]+1) buying_trend += order_book[1][i][1]/(-order_book[1][i][0]+order_book[1][0][0]+1) sell_to_buy = selling_trend/buying_trend return sell_to_buy StockHoldings_code = [int(i) for i in XXXXX.getStockHoldings(SessionID, cookie_jar)['code']] StockHoldings_purchase = [float(i) for i in XXXXX.getStockHoldings(SessionID, cookie_jar)['purchase price']] StockHoldings_current = [float(i)/100 for i in XXXXX.getStockHoldings(SessionID, cookie_jar)['current price']] StockHoldings_dict = dict() for i in range(len(StockHoldings_code)): StockHoldings_dict[StockHoldings_code[i]] = [StockHoldings_purchase[i], StockHoldings_current[i]] trade_history_dict = dict() target_url = 'url' target_parameters_lists = ['', ''] target_parameters_lists[0] = 'url'.split('&') target_parameters_lists[1] = 'url'.split('&') for i in range(2): target_parameters = dict() for ele in target_parameters_lists[i]: target_parameters[ele.split('=')[0]] = ele.split('=')[1] r = requests.post(target_url, target_parameters, request_header, cookies=cookie_jar) soup = BeautifulSoup(r.text, "html.parser") table_3 = soup.findAll('table') #売り注文の履歴を取得するコード。 while(True): N225_StockPriceData = XXXXX.getTempStockPriceData(XXXXX.getStockPriceData(SessionID, cookie_jar, '0001', ''))[-100:] buy_sell_signals = XXXXX.find_intersections(XXXXX.compare_nDayMovingAverageLines(XXXXX.calc_nDayMovingAverageLine(N225_StockPriceData, 5), XXXXX.calc_nDayMovingAverageLine(N225_StockPriceData, 25))) diff_StockPriceData = XXXXX.calc_nDayMovingAverageLine(N225_StockPriceData, 1).reset_index().values.tolist() for i in range(len(diff_StockPriceData)-1): diff_StockPriceData[-1-i][1] = diff_StockPriceData[-1-i][1] - diff_StockPriceData[-2-i][1] now_trend = ['', ''] now_extremum = ['', ''] buy_sell_signals_list = buy_sell_signals.reset_index().values.tolist() for i in range(2, len(diff_StockPriceData)): if buy_sell_signals_list[i][1] < 0: now_trend[0] = buy_sell_signals_list[i][0] now_trend[1] = 'sell' if buy_sell_signals_list[i][1] > 0: now_trend[0] = buy_sell_signals_list[i][0] now_trend[1] = 'buy' if diff_StockPriceData[i][1]*diff_StockPriceData[i-1][1] < 0: if diff_StockPriceData[i-1][1]-diff_StockPriceData[i-2][1] < 0: now_extremum[0] = diff_StockPriceData[i][0] now_extremum[1] = '極大値' elif diff_StockPriceData[i-1][1]-diff_StockPriceData[i-2][1] > 0: now_extremum[0] = diff_StockPriceData[i][0] now_extremum[1] = '極小値' print(now_trend[0], now_trend[1]) print(now_extremum[0], now_extremum[1]) print('') StockHoldings_dict_2 = dict() trade_history_dict_2 = dict() if now_trend[1] == 'buy' and now_extremum[1] == '極大値' and int(now_trend[0]) < int(now_extremum[0]): print('売注文(高い方がいい)') print('銘柄 現在値/購入金額 売注文/買注文') for i in StockHoldings_dict: #現在値/購入金額。高い方がいい。 tmp = get_sell_to_buy(i) if tmp < 1.1: continue StockHoldings_dict_2[i] = [StockHoldings_dict[i][1]/StockHoldings_dict[i][0], tmp] print(i, StockHoldings_dict[i][1]/StockHoldings_dict[i][0], tmp) time.sleep(1) if now_trend[1] == 'sell' and now_extremum[1] == '極小値' and int(now_trend[0]) < int(now_extremum[0]): print('買注文(低い方がいい)') print('銘柄 現在値/売却金額 売注文/買注文') for i in trade_history_dict: #現在値/売却金額。低い方がいい。 if trade_history_dict[i][1]/trade_history_dict[i][0] > 0.99: continue tmp = get_sell_to_buy(i) if tmp > 0.9: continue trade_history_dict_2[i] = [trade_history_dict[i][1]/trade_history_dict[i][0], tmp] print(i, trade_history_dict[i][0]/trade_history_dict[i][1], tmp) time.sleep(1) print('') print('') trader2()
この文章を読んで、面白い!役に立った!...と思った分だけ、投げ銭していただけると嬉しいです。