やってみたこと
SBI証券を使って、株のデイトレードをしている。
SBI証券HPへのログインを自動化してみた で、少しLGTMをいただけてうれしかったので、
もう少し実用的なこととして、ある期間のトレードでいくら儲かってるか、いくら損しているかがわかるようにしてみた。
具体的には、SBI証券HPから取引履歴のCSVファイルをダウンロードして、
各売買の決済損益を算出し、指定した日付からの決済損益と、その中からトップ5、ワースト5を出力してみた。
環境
- Chrome 89.0.4389.128
- ChromeDriver
- Python 3.8
コード
以下コードでは、2021年1月1日以降の履歴を取得している。
合計の決済損益と、決済損益のトップ5とワースト5が出力される。
from selenium import webdriver
from selenium.webdriver import ChromeOptions
from selenium.webdriver.chrome.webdriver import WebDriver
import csv
import io
import os
import sys
import time
WAIT_TIME = 5
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
item_code = None
def login(driver):
driver.get('https://www.sbisec.co.jp/ETGate')
loginid = driver.find_element_by_name('user_id').send_keys('userid')
passwd = driver.find_element_by_name('user_password').send_keys('password')
Log_in = driver.find_element_by_name('ACT_login').click()
def download_csvfile(driver, year, month, day):
driver.get('https://site2.sbisec.co.jp/ETGate/?_ControlID=WPLETacR007Control')
From_year = driver.find_element_by_name('ref_from_yyyy').send_keys(year)
From_month = driver.find_element_by_name('ref_from_mm').send_keys(month)
From_day = driver.find_element_by_name('ref_from_dd').send_keys(day)
Search = driver.find_element_by_name('ACT_search').click()
Download_csv = driver.find_element_by_id('csvlink').click()
def read_data(input_csv):
csv_data = []
with open(input_csv, newline='', encoding='shift-jis') as f:
# pass head rows
for (n, h) in enumerate(csv.DictReader(f), start=1):
if n >= 5:
break
input_csv_header = ['約定日', '銘柄', '銘柄コード', '市場', '取引', '期限', '預り', '課税',
'約定数量', '約定単価', '手数料/諸経費等', '税額', '受渡日',
'受渡金額/決済損益']
reader = csv.DictReader(f, input_csv_header)
for row in reader:
if item_code is None:
# pass the exception rows of stock trade
if row['取引'] != '株式現物買' and row['取引'] != '株式現物売':
continue
else:
if row['銘柄コード'] != item_code or (row['取引'] != '株式現物買' and row['取引'] != '株式現物売'):
continue
csv_data.append(row)
return csv_data
def calculate_data(csv_data):
output_data = []
for i, row in enumerate(csv_data):
amount = 0
price = 0
for j in range(i + 1, len(csv_data)):
if row['銘柄コード'] == csv_data[j]['銘柄コード']:
brand = csv_data[j]['銘柄']
brand_code = csv_data[j]['銘柄コード']
if row['取引'] == '株式現物買':
sell_day = csv_data[j]['約定日']
buy_day = row['約定日']
sell_price = csv_data[j]['約定単価']
buy_price = row['約定単価']
sell_amount = csv_data[j]['約定数量']
buy_amount = row['約定数量']
if amount == 0:
amount = int(buy_amount) - int(sell_amount)
price = float(csv_data[j]['受渡金額/決済損益']) - float(row['受渡金額/決済損益'])
else:
amount -= int(sell_amount)
price += float(csv_data[j]['受渡金額/決済損益'])
if amount == 0:
item = {'現買日': buy_day,
'現売日': sell_day,
'銘柄': brand,
'銘柄コード': brand_code,
'購入数量': buy_amount,
'現買単価': buy_price,
'現売単価': sell_price,
'決済損益': price}
else:
buy_day = csv_data[j]['約定日']
sell_day = row['約定日']
buy_price = csv_data[j]['約定単価']
sell_price = row['約定単価']
buy_amount = csv_data[j]['約定数量']
sell_amount = row['約定数量']
if amount == 0:
amount = int(buy_amount) - int(sell_amount)
price = float(row['受渡金額/決済損益']) - float(csv_data[j]['受渡金額/決済損益'])
else:
amount += int(buy_amount)
price -= float(csv_data[j]['受渡金額/決済損益'])
if amount == 0:
item = {'現買日': buy_day,
'現売日': sell_day,
'銘柄': brand,
'銘柄コード': brand_code,
'購入数量': buy_amount,
'現買単価': buy_price,
'現売単価': sell_price,
'決済損益': price}
if amount == 0:
csv_data.pop(j)
output_data.append(item)
break
return output_data
def write_data(output_data):
output_csv = 'output.csv'
output_csv_header = ['現買日', '現売日', '銘柄', '銘柄コード', '購入数量', '現買単価',
'現売単価', '決済損益']
with open(output_csv, 'w', newline='', encoding='utf-8') as f:
writer = csv.DictWriter(f, fieldnames=output_csv_header)
writer.writeheader()
total = 0
for row in output_data:
writer.writerow(row)
total += float(row['決済損益'])
print('\"total record: {}'.format(len(output_data)))
print('total gain/loss: {}'.format(total))
top_list = {}
top_list = sorted(output_data, key=lambda x: x['決済損益'], reverse=True)
bottom_list = {}
bottom_list = sorted(output_data, key=lambda x: x['決済損益'])
print('\n=TOP5=')
for i in range(5 if len(top_list) >= 5 else len(top_list)):
print(top_list[i])
print('\n=BOTTOM5=')
for i in range(5 if len(bottom_list) >= 5 else len(bottom_list)):
print(bottom_list[i])
# quotation
print('\"')
def main():
# setting folder for downloading
downloadsFilePath = '.\\'
options = ChromeOptions()
prefs = {
"profile.default_content_settings.popups": 1,
"download.default_directory":
os.path.abspath(downloadsFilePath) + r"\\",
"directory_upgrade": True
}
options.add_experimental_option("prefs", prefs)
driver = webdriver.Chrome(executable_path=r'./chromedriver.exe', options=options)
driver.implicitly_wait(WAIT_TIME)
login(driver)
Account = driver.find_element_by_xpath('//a[img/@title="口座管理"]').click()
# download csv file from 2021/01/01
download_csvfile(driver, '2021', '01', '01')
time.sleep(WAIT_TIME)
# get the latest csv file name
filename = None
if len(os.listdir(downloadsFilePath)) != 0:
filename = max([downloadsFilePath + '\\'+ f for f in os.listdir(downloadsFilePath) if f.endswith('.csv')], key=os.path.getctime)
driver.close()
csv_data = read_data(filename)
output_data = calculate_data(csv_data)
write_data(output_data)
if __name__== '__main__':
main()
これからやってみること
- 合計決済損益とトップ5、ワースト5を、毎日自分のメールアドレスに送信するようにサーバーに設定すれば、毎日自動的にトレード状況をチェックできてうれしいかも