春は曙 夏は夜 秋は夕暮れ 冬はつとめて・・・・。
春は野草
夏はガサガサ
秋は釣り
冬は森・・・
・・・・・と
自然と戯れて現実逃避し過ぎた・・。
最近は、
サバイバル力あればお金無くても生きていけるじゃん。
と思い始めている。
・・・・逃げちゃ駄目だ!
ゴールデンウィークに作っていたライブラリを今更公開(まだ作りかけ)しておく。
再度、Mechanize、Seleniumライブラリの比較
近々、証券会社がREST APIを公開される可能性があるが、独自で作るなら有名なライブラリには次のものがある。
ライブラリ名 | 実行速度 | コード量 |
---|---|---|
requests | 早い | 多い |
Mechanize | 普通 | 少ない |
Selenium | やや遅い | 少ない |
SBI証券では、聞くところによると1.5秒以内の高速処理が出来ない制約がついているらしい。
であればコード量との費用対効果より「Mechanize」を使用する。
Seleniumは、一銘柄の購入まで22秒かかったと書かれている記事も存在したし、有名すぎて今更感
と以前の日記を読むと書いてあった。
Mechanizeはブラウザが起動しないから不具合があるときに何が問題が分からない。
Seleniumが有名だから使わない
とか理由になってないよね、バカなの自分。
Seleniumで良いでしょ!
もともと、徳山秀樹式デイトレード理論をProtra無しで実現するために始めた。
今度はSelenium使って信用取引口座の買いを実装してみる。
ソースコード
「chromedriver.exe」を予めダウンロードして同じフォルダに入れておくこと。
Mechanizeを使ったライブラリ「SBIcomm」を誰かが作っていたが、それを拝借してSelenium用にしてみる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
import re import sys import csv import time import urllib from datetime import datetime # for debug import requests from selenium import webdriver from selenium.common.exceptions import NoSuchElementException from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.webdriver.support.ui import Select class COMP: MORE = '0' LESS = '1' def __init__(self): pass class CATEGORY: SPC = '0' STD = '1' def __init__(self): pass class ORDER: LIM_UNC = ' ' # 指値無条件 LIM_YORI = 'Z' # 指値寄指 LIM_HIKI = 'I' # 指値引指 LIM_HUSE = 'F' # 指値不成 LIM_IOC = 'P' # 指値IOC MRK_UNC = 'N' # 成行無条件 MRK_YORI = 'Y' # 成行寄成 MRK_HIKI = 'H' # 成行引成 MRK_IOC = 'O' # 成行IOC def __init__(self): pass _BASE_URL = "https://k.sbisec.co.jp" _STOCK_DIR = _BASE_URL + "/bsite/member/stock" _ACC_DIR = _BASE_URL + "/bsite/member/acc" _MARGIN_DIR = _BASE_URL + "/bsite/member/margin" class SBIcomm: """ SBI証券のサイトをスクレイピングして株価の情報取得やオーダーの送信等のやりとりを行うクラス """ # URL pages = {'top': _BASE_URL + "/bsite/visitor/top.do", 'search': _BASE_URL + "/bsite/price/search.do", 'market': _BASE_URL + "/bsite/market/indexDetail.do", 'credit_buy': _MARGIN_DIR + "/buyOrderEntry.do"} def __init__(self, username, password, proxy=None, proxy_user=None, proxy_password=None): """ コンストラクタ :param str username: SBI証券でのユーザ名 :param str password: パスワード :param str proxy: プロキシ :param str proxy_user: プロキシのユーザ名 :param str proxy_password: プロキシのパスワード """ self._username = username self._password = password self._proxy = proxy self._proxy_user = proxy_user self._proxy_password = proxy_password # ブラウザ起動 self._br = self._open_browser(self._add_url_param(self.pages['top'], {})) self._br.find_element_by_name("username").send_keys(self._username) self._br.find_element_by_name("password").send_keys(self._password) def __del__(self): """ デストラクタ """ self._br.close() self._br.quit() def _add_url_param(self, url, params): return url + '?' + urllib.parse.urlencode(params) def _get_authorized_webdriver(self, url): """ Go though azure certification :param str url: Opened url(str :return Instance of selenium """ options = webdriver.ChromeOptions() # options.add_argument('--headless') options.add_argument('--log-level=3') options.add_argument('--no-sandbox') # Bypass OS security model driver = webdriver.Chrome('chromedriver.exe', options=options) driver.get(url) while True: # print(driver.current_url) if url in driver.current_url: break time.sleep(1) return driver def _open_browser(self, page): """ Open url on selenium :param str url: Opened url(str :return Instance of selenium """ # print(page, flush=True) driver = self._get_authorized_webdriver(page) session = requests.session() for cookie in driver.get_cookies(): session.cookies.set(cookie["name"], cookie["value"]) return driver def _get_current_value(self): """ Value、日付・時間を返す """ try: path_list = self._br.find_elements_by_xpath("//font[@class=\"ltext\"]") # SeleniumはテキストをWebElementで扱えない date = self._br.find_elements_by_xpath("//form") for item in date[0].text.splitlines(): if ('(' in item): # print(item, flush=True) day = re.findall('([0-9]+/[0-9]+) ([0-9]+:[0-9]+) ', item) break current_price = float(path_list[0].text.replace(",","")) current_price = int(current_price) # print(day, (current_price), flush=True) return day, (current_price) except ValueError: print("Cannot float! %s" % code) return [('N/A', 'N:A')], None except: print("Cannot Get Value! %s" % code) return [('N/A', 'N:A')], None def buy_order_credit_by_value( self, code, quantity=None, price=None, limit="today", order=ORDER.LIM_UNC, category=CATEGORY.SPC, inv=False, comp=COMP.MORE, trigger_price=None, payment_limit="D"): """ 現在の株価と購入希望額を確認して低ければ信用で購入 :param str code: 企業コード :param str quantity: 購入数 :param str price: 購入金額 :param str limit: 期間指定 today=当日中、week=今週中、期間(2020/10/30) :param str order: 指値無条件等 :param str payment_limit: 日計り(D) 制度信用(6ヶ月)(6) """ self._br.find_element_by_name("login").click() # ページ表示 self._br.get(self._add_url_param(self.pages['credit_buy'], {"ipm_product_code": code, "market": "SOR", "cayen.isStopOrder": str(inv).lower()})) # 現在値取得 # 確認ボタンをクリック self._br.find_elements_by_xpath(".//input[@type='submit']")[0].click() current_day, (current_price) = self._get_current_value() print(current_day, (current_price), flush=True) # 入力 self._br.find_element_by_name("quantity").send_keys(quantity) self._br.find_element_by_name("price").send_keys(price) # self._br.find_element_by_name("password").send_keys(self._password) element = self._br.find_element_by_name("sasinari_kbn") select = Select(element) select.select_by_value(order) element = self._br.find_element_by_name("payment_limit") select = Select(element) select.select_by_value(payment_limit) if limit == "today": # radioボタンが押せない場合は、clickでなくsend_keys(Keys.SPACE)で試す self._br.find_elements_by_xpath(".//input[@type='radio' and @value='today']")[0].send_keys(Keys.SPACE) elif limit == "week": # print("week", flush=True) # radioボタンが押せない場合は、clickでなくsend_keys(Keys.SPACE)で試す self._br.find_elements_by_xpath(".//input[@type='radio' and @value='week']")[0].send_keys(Keys.SPACE) else: # print("limit", flush=True) # radioボタンが押せない場合は、clickでなくsend_keys(Keys.SPACE)で試す self._br.find_elements_by_xpath(".//input[@type='radio' and @value='limit']")[0].send_keys(Keys.SPACE) element = self._br.find_element_by_name("limit") select = Select(element) select.select_by_visible_text(limit) while True: time.sleep(1) return 0, 0 USERNAME = "XXXXXXX" PASSWORD = "YYYYYYY" # 購入銘柄毎に購入処理 def main(): start = time.time() # SBI証券ログイン sbi = SBIcomm(USERNAME, PASSWORD) date, value = sbi.buy_order_credit_by_value("2158", "100", "767", limit="2020/11/10") # del sbi elapsed_time = time.time() - start print ("elapsed_time:{0}".format(elapsed_time) + "[sec]") return True if __name__ == '__main__': main() |
デバッグ(ブラウザを表示)したい時は「options.add_argument(‘–headless’)」を有効化すれば良い。
とりあえず動いているのを見るのは楽しい。
まとめ
ログインして発注まで行うことができた。
SBI証券では、日取りの信用取引による売買の方が手数料が安いので、少しずつ拡張していくことにする。
このコードは半年前に書いて放置してたものだ・・・・そろそろシストレの学習再開しないとなぁ。。