PythonでIPO自動申込@SBI証券を実装してみた

## 目次
[0.結論](#0-結論)
[1.はじめに](#1-はじめに)
[2.IPO申込＠SBI証券](#2-ipo申込sbi証券)
[3.IPO銘柄ランク確認](#3-ipo銘柄ランク確認)
[4.LINE通知](#4-line通知)
[5.おわりに](#5-おわりに)

### 0. 結論
Python（Selenium）を用い、SBI証券でのIPO申込（スクレイピングにより自動処理）が可能。
また、申込IPO銘柄のランクを取得し、その内容（申込IPO銘柄名とランク）をLINEにて通知。
本内容をコピペし、自身のSBI証券のパスワードへと書き換えることで、誰でも活用可能。

### 1. はじめに
2024年度から新NISAがスタートし、投資に興味が出ている人が多くなっていると感じます。

新NISAでの投資は投資信託、個別株への投資がメインだと思いますが、利益を得やすい投資手法として**IPO投資**というものがあります。

▼参考サイト
[IPOのメリット・デメリット](https://www.rakuten-card.co.jp/minna-money/securities/stock/article_2105_00001/#:~:text=IPO%E6%8A%95%E8%B3%87%E3%81%AE%E3%83%A1%E3%83%AA%E3%83%83%E3%83%88%E3%81%AF,%E3%81%B0%E8%B2%B7%E3%81%88%E3%81%AA%E3%81%84%E3%80%8D%E3%81%93%E3%81%A8%E3%81%A7%E3%81%99%E3%80%82)

利益を得やすい**IPO投資**ですが、上記記事内でも言及されている通り、**抽選に当たらなければ購入できない**というハードルがあります。

当たり前の話ですが**抽選に当たる**ためには**抽選に申込**することが必要となります。

SBI証券においてはIPOチャレンジポイントという制度が導入されており、**興味がない銘柄に対しても抽選に申込する**ことへのインセンティブ設計がなされています。

▼参考サイト
[SBI証券のIPOチャレンジポイント](https://www.ipokiso.com/data/sbi_challenge_point.html)

しかし、**IPO銘柄は年間約100銘柄が上場**しており、全ての銘柄に対して申込を行うことは非常に手間のかかる作業となってしまいます。

そのため、今回はPythonを用い、**SBI証券でのIPO申込を自動で行えるスクリプトを開発した**ので、紹介したいと思います。

スクリプトは大きく分けて３つのパート「**IPO申込＠SBI証券**」「**IPO銘柄ランク確認**」「**LINE通知**」に分けられますので、それぞれを紹介していきます。

なお開発環境ですが**Jupyter Notebook**を利用しています。

普段はGoogle Colaboratoryを使用して開発しているのですが、スクレイピング処理をする際にはJupyter Notebookの方が開発しやすいです。

その理由はスクレイピング処理実行時に**Jupyter Notebookではブラウザが起動し、実行状況が表示される**のですが、**Google Colaboratoryではブラウザが起動せず、実行状況が表示されない**ためです。

では、以下から作成したスクリプトについて紹介していきます。

### 2. IPO申込＠SBI証券
ここでは、作成したスクリプトのメインの部分となるSBI証券にてIPOを申込する処理について紹介していきたいと思います。

まずはスクレイピング用のライブラリである**Selenium**とその他ライブラリをインストールします。

▼Selenium参考サイト
[Python + Selenium で Chrome の自動操作を一通り](https://qiita.com/memakura/items/20a02161fa7e18d8a693)

```Python:
#seleniumとchromedriverのimport
from selenium import webdriver
import chromedriver_binary
#Option設定のimport
from selenium.webdriver.chrome.options import Options
```

```Python:
#周辺環境のimport
from time import sleep
import csv
import datetime
import requests
import re
import os
import shutil
```

以下の内容はブラウザが起動し、実行状況が表示されるモード（**非headlessモード**）でスクレイピング処理が行われる設定です。

実装時には実際の処理を確認しながら開発していくと思いますので、以下の設定が良いです。
```Python:
#driverの作成
driver = webdriver.Chrome()
```

以下の内容はブラウザが起動せず、実行状況が表示されないモード（**headlessモード**）でスクレイピング処理が行われる設定です。

運用時には実行状況の確認は必要ないと思いますので、以下の設定が良いです。

開発時には、この部分をコメントアウトしないとheadlessモードでの実行となりますので、コメントアウトすることがおすすめです。
```Python:
#optionにてheadlessの設定
options = Options()
options.add_argument('--headless')
#driverの作成
driver = webdriver.Chrome(options=options)
```

以下の内容はスクレイピング処理を行うURL（今回はSBI証券）の設定です。
URLを２つ設定しているのは、ページ遷移高速化のためです。
ページ遷移について、直接指定の方がスクレイピングでの遷移よりも高速となるため、事前にわかっているURLについては明示的に設定する方が良いです。
```Python:
#URLの設定
URL_short = 'https://www.sbisec.co.jp'
URL = 'https://www.sbisec.co.jp/ETGate'
```

以下の内容はSBI証券でのユーザー名や各種パスワードの設定です。
また、ここではIPO申込株数についても設定しております。
実際に自身で実行してみる際には、ここに自身のユーザー名等を記載し、実行してください。
```Python:
#ユーザー名、passの登録(自分のユーザー名、passを登録すれば実際に実行できます)
USERNAME = 'XXXXXXXXXX'
PASSWORD = 'XXXXXXXXXX'
ORDER_NUM = '500'#IPO銘柄申込株数
ORDER_PASS = 'XXXXXXXXXX'
```

以下にてブラウザが起動し、SBI証券のトップページが開かれます。
```Python:
#URLの設定
driver.get(URL)
sleep(1)
```

以下にてSBI証券のログイン処理を実行しています。
```Python:
#ログイン情報欄の取得、入力
error_flg = False
try:
    #ユーザーネーム欄の取得、入力
    username_input = driver.find_element_by_xpath('//input[@name="user_id"]')
    username_input.send_keys(USERNAME)
    sleep(1)
    
    #パスワード欄の取得、入力
    password_input = driver.find_element_by_xpath('//input[@name="user_password"]')
    password_input.send_keys(PASSWORD)
    sleep(1)
    
    #ログインボタンの押下
    login_button = driver.find_element_by_xpath('//input[@name="ACT_login"]')
    login_button.submit()
    sleep(1)
    
#エラー時の例外処理    
except Exception:
    error_flg = True
    print('ログイン時にエラーが発生しました')
```

以下にてIPO一覧画面へ遷移しています。
```Python:
#IPO一覧ページへ移動
ALL_IPO_URL = 'https://m.sbisec.co.jp/oeliw011?type=21'
if error_flg is False:
    try:
        driver.get(ALL_IPO_URL)
        sleep(1)
    #例外処理 
    except Exception:
        error_flg = True
        print('検索時にエラーが発生しました')
```

以下にてIPO一覧画面の中から申込可能なIPO銘柄を探索し、その銘柄の申込画面へ遷移しています。
申込可能なIPO銘柄がない場合は処理が停止します。
```Python:
#IPO一覧ページからIPO銘柄個別ページへ移動
if error_flg is False:
    try:
        IPO_button = driver.find_element_by_xpath('//img[@alt="申込"]/parent::a')
        IPO_button.click()
        sleep(1)
    #例外処理 
    except Exception:
        error_flg = True
        print('検索時にエラーが発生しました')
        print('申込できるIPO銘柄がないです')
```

以下にてIPO申込画面で設定したIPO申込株数、取引パスワードを入力し、申込処理をして、申込確認画面に遷移します。

```Python:
#IPO銘柄ページで情報の入力
if error_flg is False:
    try:
        order_num = driver.find_element_by_xpath('//input[@name="suryo"]')
        order_num.send_keys(ORDER_NUM)
        sleep(1)

        order_price = driver.find_element_by_xpath('//input[@id="strPriceRadio"]')
        order_price.click()
        sleep(1)

        order_pass = driver.find_element_by_xpath('//input[@name="tr_pass"]')
        order_pass.send_keys(ORDER_PASS)
        sleep(1)

        order_button = driver.find_element_by_xpath('//input[@type="submit"]')
        order_button.submit()
    #例外処理 
    except Exception:
        error_flg = True
        print('情報入力時にエラーが発生しました')
```

以下にてIPO申込確認画面で確認処理をしています。

```Python:
#申込確認ページ
if error_flg is False:
    try:
        #申込をしたIPO銘柄名を取得
        IPO_name = driver.find_element_by_xpath('//font[@class="lbody"]/child::b')
        IPO_name = IPO_name.text
        
        order_button_fin = driver.find_element_by_xpath('//input[@name="order_btn"]')
        order_button_fin.click()
    #例外処理 
    except Exception:
        error_flg = True
        print('申込確認時にエラーが発生しました')
```

上記のコードを実行することでスクレイピング処理を用いた、SBI証券にてIPOを申込することが可能となります。

### 3. IPO銘柄ランク確認
ここでは、作成したスクリプトのサブの部分となる申し込んだIPO銘柄のランク（有望度）を確認する処理について紹介していきたいと思います。

まず、IPO銘柄と一概に言っても利益が出そうな銘柄と出なさそうな銘柄があり、それについては以下のサイトにてまとめられています。

▼参考サイト
[IPO企業の評価一覧表](https://www.ipokiso.com/company/index.html)

SBI証券にてIPOを申し込んだ後に、上記サイトから申込銘柄のランク（有望度）を取得していくのが以下の処理となります。


まずは、URLの設定です。
```Python:
#以下はIPO銘柄の有望度取得関連
#URLの設定
URL = 'https://www.ipokiso.com/company/index.html'
```

次に、IPO申込銘柄の文字を検索しやすいように成形します。
```Python:
#IPO銘柄名
IPO_name = IPO_name.replace('（株）','')
```

以下にてブラウザが起動し、IPO銘柄の評価一覧が記載されたサイトのトップページが開かれ、トップページを一番下までスクロールしています。

サイト内にjavascriptが埋め込まれている場合は、サイト訪問だけでは全ての情報が取得できないので、スクロール処理を実行することにより、全ての情報が取得できるようになります。
```Python:
#URLの設定
driver.get(URL)
sleep(1)

#一度画面を一番下までゆっくりスクロール(xの値を大きくするとスクロールの速度早くなる)
height = driver.execute_script('return document.body.scrollHeight;')
width = driver.execute_script('return document.body.scrollWidth;')
driver.set_window_size(width,height)
for x in range(1,int(height/3)):
    driver.execute_script('window.scrollTo(0, '+str(int(x*3))+');')
```

以下にて申込IPO銘柄のページへ遷移します。

```Python:
#IPO銘柄の個別ページへ移動
IPO_info = driver.find_element_by_xpath(f'//b[contains(text(), "{IPO_name}")]/parent::a')
IPO_info_url = IPO_info.get_attribute('href')
IPO_info.click()
```

以下にて申込IPO銘柄のランクを取得します。

```Python:
#IPO銘柄のランクの取得
Rank = 0
if len(driver.find_elements_by_xpath('//img[@alt="S"]')) ==1: Rank = 'S'
if len(driver.find_elements_by_xpath('//img[@alt="A"]')) ==1: Rank = 'A'
if len(driver.find_elements_by_xpath('//img[@alt="B"]')) ==1: Rank = 'B'
if len(driver.find_elements_by_xpath('//img[@alt="C"]')) ==1: Rank = 'C'
if len(driver.find_elements_by_xpath('//img[@alt="D"]')) ==1: Rank = 'D'
```

上記のコードを実行することで申込IPO銘柄のランク（有望度）の取得が可能となります。

### 4. LINE通知
ここでは、作成したスクリプトのサブの部分となる申込IPO銘柄名、およびその銘柄のランクをLINEにて通知する処理について紹介していきたいと思います。

LINE Notifyというサービスを使用することにより、簡単にLINEへの通知を行うことができます。

以下のサイトを参考にLINE Notifyのトークンを取得し、以下のコードを実行することで、申込IPO銘柄名、およびその銘柄のランクをLINEにて通知可能です。

▼参考サイト
[PythonでLINE Notifyへ通知を送る](https://qiita.com/akeome/items/e1e0fecf2e754436afc8)

まず、LINE Notifyのトークン情報を記載します。
```Python:
#LINE通知の準備
url = 'https://notify-api.line.me/api/notify'
access_token = 'XXXXXXXXXX'
headers = {'Authorization': 'Bearer ' + access_token}
```

その後、申込IPO銘柄名、およびその銘柄のランク（＋情報が記載されているサイトのURL）を通知する処理について記載しています。
```Python:
#LINE通知の発信
message = IPO_name +' ： '+ Rank +' \n '+ IPO_info_url
payload = {'message': message}
r = requests.post(url, headers=headers, params=payload,)
```

### 5. おわりに
初めてスクレイピングによる自動処理を開発してみましたが、自分の思った通りの動作ができてよかったです。

また、メインではないですが、３章、４章の処理を加えることにより自身の理解を深めること、処理の見える化ができたと思います。

課題としてはGitHubの登録をしていないので、スクリプト全体を一括で掲載できていない点ですが、今後のスクリプトはGoogle Colaboratoryでの共有機能を用いて掲載しようと思っています。

ぜひ、本スクリプトを活用し、良い投資生活を！

長い文章を最後までお読みいただき、ありがとうございました！！