【ADRリストを作りたい】 ~三部作 第一話~  YahooFinanceから米国株一覧の取得

- [x] 忙しくてADR銘柄を比較してる時間がない,,
- [x] リストがあれば、すぐ選べるのに,,
- [x] 資金少ないし、失敗したくないなぁ,,

<br>
そんな方でも大丈夫です！
三部作のゴールは、**時価総額順**、**業種別**、**指定額範囲**で検索できる、ADR銘柄のリストの作り方がわかります。
それによって調べたい時価総額や業種を絞り込んで、パッと比較できるようになります。
<br>


<details>
<summary><strong>〜目次〜</strong></summary>
 [1. yahoofinanceから米国上場銘柄の取得](#1-yahoofinanceから米国上場銘柄の取得)
　 [1-1. モジュールのインポート](#1-1-モジュールのインポート)
　 [1-2. 表示行数の設定](#1-2-表示行数の設定)
　 [1-3. urlの作成](#1-3-urlの作成)
[2. データの整形](#2-データの整形)
　 [2-1. データフレームの結合](#2-1-データフレームの結合)
　 [2-2. 数字のみ抽出](#2-2-数字のみ抽出)
　 [2-3. 単位千を000に変換](#2-3-単位千を000に変換)
　 [2-4. ドル円の現在価格を取得](#2-4-ドル円の現在価格を取得)
　 [2-5. 時価総額を円表示してデータフレームに追加](#2-5-時価総額を円表示してデータフレームに追加)
　 [2-6. 一株の価格を数値のみ表示](#2-6-一株の価格を数値のみ表示)
　 [2-7. 小数点以下の表示数を指定](#2-7-小数点以下の表示数を指定)
　 [2-8. 列の追加](#2-8-列の追加)
　 [2-9. 列の除去](#2-9-列の除去)
　 [2-10. 列の入れ替え](#2-10-列の入れ替え)
　 [2-11. 列要素の編集](#2-11-列要素の編集)
[3. 検索](#3-検索)
　 [3-1. 時価総額の範囲を指定](#3-1-時価総額の範囲を指定)
　 [3-2. 一株円の価格範囲を指定](#3-2-一株円の価格範囲を指定)
[4. 終わりに](#4-終わりに)
</details>


#1. yahoofinanceから米国上場銘柄の取得
####1-1. モジュールのインポート
```python
import pandas as pd# データ分析
import pandas_datareader# Pandasの0.19.0からサポートされなくなって、独立して使われている
import numpy as np# 計算処理
import time# sleepを入れる
import re# 正規表現の表示と編集
```
基本的にpandasを使用します。

<br>
####1-2. 表示行数の設定
```python
# 表示行数の設定
# 4の箇所を、Noneにすると無制限表示
pd.set_option("display.max_rows", 4)
```
取得する銘柄は6800行のデータフレームになります。
全て表示するとデータフレーム壁ができて見にくいので、好みで行数を設定して下さい。

<br>
####1-3. urlの作成
```python
# YahooFinanceから、NASDAQ/NYSE/OTCに上場している銘柄の取得
urls = ["https://stocks.finance.yahoo.co.jp/us/ranking/?kd=4&tm=d&mk=&adr=&cg=&idx=&brk=&p={}".format(i) for i in range(1,137)]
```
YahooFinenceから、NASDAQ/NYSE/OTCに上場している銘柄一覧を取得するためのurlリストを作成。
urlの末番号が違うだけなので、format(i)にfor文で数字を入れ込んでいきます。
>`出力結果`
['https://stocks.finance.yahoo.co.jp/us/ranking/?kd=4&tm=d&mk=&adr=&cg=&idx=&brk=&p=1',
 'https://stocks.finance.yahoo.co.jp/us/ranking/?kd=4&tm=d&mk=&adr=&cg=&idx=&brk=&p=2',
 'https://stocks.finance.yahoo.co.jp/us/ranking/?kd=4&tm=d&mk=&adr=&cg=&idx=&brk=&p=3',
 'https://stocks.finance.yahoo.co.jp/us/ranking/?kd=4&tm=d&mk=&adr=&cg=&idx=&brk=&p=4',
 ... ... ... ... ...
 'https://stocks.finance.yahoo.co.jp/us/ranking/?kd=4&tm=d&mk=&adr=&cg=&idx=&brk=&p=133',
 'https://stocks.finance.yahoo.co.jp/us/ranking/?kd=4&tm=d&mk=&adr=&cg=&idx=&brk=&p=134',
 'https://stocks.finance.yahoo.co.jp/us/ranking/?kd=4&tm=d&mk=&adr=&cg=&idx=&brk=&p=135',
 'https://stocks.finance.yahoo.co.jp/us/ranking/?kd=4&tm=d&mk=&adr=&cg=&idx=&brk=&p=136']

<dr>
<dr>

#2. データの整形
データ整形が作業のほとんどになるかと思います。
整形が終われば、要素を組合わせる**非常に楽しい工程**が待っています。
ですので、それまでお付き合い下さい。

####2-1. データフレームの結合
```python
# データフレーム化して結合
# ignore_index=Trueがなくても取得できるがindex番号が結合されない
urls_read = [pd.read_html(url_read, encoding="utf-8", skiprows=[51])[0] for url_read in urls]
time.sleep(2)
df = pd.concat(urls_read, ignore_index=True)
```
取得してきたデータフレームを結合して、一つのデータフレームにします。
取得から結合ができていれば、下の結果が返ってきます。
もしエラーになる方は、1-3でやったrange(urlの取得ページ数)を一つ減らしてみて下さい。
>`出力結果`
	順位	名称・ティッカー・市場	取引値	前日比・前日差	時価総額	掲示板
0	1	アップル[AAPL] - NASDAQ	121.21(03/26 17:20)	+0.51%(+0.62)	2,034,885,116千	掲示板
1	2	マイクロソフト[MSFT] - NASDAQ	236.48(03/26 17:32)	+1.78%(+4.14)	1,783,583,185千	掲示板
...	...	...	...	...	...	...
6798	6799	ナショナル・リテール…[NNN-PE] - NYSE	25.09(10/01 19:23)	-%(---)	2,885千	掲示板
6799	6800	アメリカン・ケアソー…[GNOW] - NASDAQ	0.17(05/15 01:10)	-%(---)	2,822千	掲示板
6800 rows × 6 columns

<br>
####2-2. 数字のみ抽出
```python
# 列要素の整形（時価総額列から数字のみを抽出）
rep_df = df['時価総額'].str.replace('千',',').str.replace(",","")
```
時価総額で範囲検索するために、単位「千」を除去。

>`出力結果`
0       2034885116
1       1783583185
           ...    
6798          2885
6799          2822
Name: 時価総額, Length: 6800, dtype: object

<br>
####2-3. 単位千を000に変換
```python
# 時価総額列はまだsrt型なので、数字をint型にして列に追加
df.assign(時価総額_ドル = rep_df.astype(np.int)*1000)
coldf = df.assign(時価総額_ドル = rep_df.astype(np.int)*1000)
```
int型にした要素に1000をかけて桁を合わせます。
列名を「時価総額_ドル」に変えて、データフレームに追加。
>`出力結果`
順位	名称・ティッカー・市場	取引値	前日比・前日差	時価総額	掲示板   時価総額_ドル
0	1	アップル[AAPL] - NASDAQ	121.21(03/26 17:20)	+0.51%(+0.62)	`2,034,885,116千`	掲示板	`2034885116000`
1	2	マイクロソフト[MSFT] - NASDAQ	236.48(03/26 17:32)	+1.78%(+4.14)	1,783,583,185千	掲示板	1783583185000
...	...	...	...	...	...	...	...
6798	6799	ナショナル・リテール…[NNN-PE] - NYSE	25.09(10/01 19:23)	-%(---)	2,885千	掲示板	2885000
6799	6800	アメリカン・ケアソー…[GNOW] - NASDAQ	0.17(05/15 01:10)	-%(---)	2,822千	掲示板	2822000
6800 rows × 7 columns

<br>
####2-4. ドル円の現在価格を取得
```python
# 現在の為替の価格を表示
djdf = pd.read_html("https://stocks.finance.yahoo.co.jp/stocks/detail/?code=USDJPY=X",encoding="utf-8")[0]

# ilocでデータフレームの表示する箇所を[x,y]でピンポイント表示
usd_jpy_df = djdf.iloc[0,1]
```
ドル円の現在価格は後でも使うので、ここで取得しておきましょう。
例えば一株・一証券が、何円で買えるかの一覧が取得可能になります。

<br>
####2-5. 時価総額を円表示してデータフレームに追加
```python
# [時価総額_ドル]列にドル円の現在値をかけて円表示
all_col_df2 = coldf["時価総額_ドル"]*usd_jpy_df
# 整数にする
all_col_df3 = all_col_df2.astype(int) 
# 列に追加
all_col_df4 = coldf.assign(時価総額_円 = all_col_df3)
```
日本円でも検索できるようにしておきましょう。
工程は先ほどと同じで、データフレームから編集したい列を指定します。
その列に現在のドル円価格をかけて、元のデータフレームに追加。
>`出力結果`
順位	名称・ティッカー・市場	取引値	前日比・前日差	時価総額	掲示板	時価総額_ドル	時価総額_円
0	1	アップル[AAPL] - NASDAQ	121.21(03/26 17:20)	+0.51%(+0.62)	2,034,885,116千	掲示板	2034885116000	`223104804118240`
1	2	マイクロソフト[MSFT] - NASDAQ	236.48(03/26 17:32)	+1.78%(+4.14)	1,783,583,185千	掲示板	1783583185000	195552060403400
...	...	...	...	...	...	...	...	...
6798	6799	ナショナル・リテール…[NNN-PE] - NYSE	25.09(10/01 19:23)	-%(---)	2,885千	掲示板	2885000	316311400
6799	6800	アメリカン・ケアソー…[GNOW] - NASDAQ	0.17(05/15 01:10)	-%(---)	2,822千	掲示板	2822000	309404080

<br>
####2-6. 一株の価格を数値のみ表示
```python
# 取引値の文字の整形、一旦全てカンマにして最後にカンマを消す
rep_df2 = all_col_df4['取引値'].str.replace('(',',').str.replace(")",",").str.replace(" ",",").str.replace("/",",").str.replace(":",",").str.replace(",","")
```
Appleの取引値で説明すると、
`121.21(03/26 17:20)`を`121.2103261720`にしています。

<br>
####2-7. 小数点以下の表示数を指定
```python
# object型を強制的にfloat方に変換する
all_col_df5 = pd.to_numeric(rep_df2 , errors="coerce")
all_col_df5 = all_col_df5.astype("float")

# ドル円をかけて、一株あたりの円価格を表示
# round()で、小数点以下2位まで表示
#all_col_df5 = (all_col_df5*usd_jpy_df).round(2)
all_col_df5 = all_col_df5.round(2)
all_col_df5 = all_col_df5*usd_jpy_df
```
2-6.で得た要素を小数点以下2位まで表示して、ドル円の現在価格をかける。
現在時点でのドル円価格は110.37jpy/usd
アップルだと`121.2103261720*110.37`で`13289.50`になります。
>`出力結果`
順位	名称・ティッカー・市場	取引値	前日比・前日差	時価総額	掲示板	時価総額_ドル	時価総額_円	`一株_円`
0	1	アップル[AAPL] - NASDAQ	121.21(03/26 17:20)	+0.51%(+0.62)	2,034,885,116千	掲示板	2034885116000	223104804118240	`13289.50`
1	2	マイクロソフト[MSFT] - NASDAQ	236.48(03/26 17:32)	+1.78%(+4.14)	1,783,583,185千	掲示板	1783583185000	195552060403400	25927.70
...	...	...	...	...	...	...	...	...	...
6798	6799	ナショナル・リテール…[NNN-PE] - NYSE	25.09(10/01 19:23)	-%(---)	2,885千	掲示板	2885000	316311400	2750.98
6799	6800	アメリカン・ケアソー…[GNOW] - NASDAQ	0.17(05/15 01:10)	-%(---)	2,822千	掲示板	2822000	309404080	18.70
6800 rows × 9 columns

<br>
####2-8. 列の追加
```python
# 上で得た一株あたりの円価格を列に追加
all_col_df5 = all_col_df4.assign(一株_円=all_col_df5)
all_col_df5
```
>`出力結果`
	順位	名称・ティッカー・市場	取引値	前日比・前日差	時価総額	掲示板	時価総額_ドル	時価総額_円	一株_円
0	1	アップル[AAPL] - NASDAQ	149.10(17:20)	+0.14%(+0.21)	2,464,647,751千	掲示板	2464647751000	270051454077069	16336.8870
1	2	マイクロソフト[MSFT] - NASDAQ	292.85(17:20)	+1.05%(+3.04)	2,200,735,902千	掲示板	2200735902000	241134632782140	32087.5745
...	...	...	...	...	...	...	...	...	...
6798	6799	プロフェッショナル・…[IPDN] - NASDAQ	1.26(17:20)	-8.03%(-0.11)	18,819千	掲示板	18819000	2061997829	138.0582
6799	6800	メディアコ・ホールデ…[MDIA] - NASDAQ	7.72(17:20)	-13.26%(-1.18)	18,818千	掲示板	18818000	2061888259	845.8804

<br>
####2-9. 列の除去
```python
#不要なカラムの除去(元データは更新されない)
all_col_df5.drop(["名称・ティッカー・市場","時価総額","順位","前日比・前日差","掲示板"],axis=1)
col_pic_df = all_col_df5.drop(["名称・ティッカー・市場","時価総額","順位","前日比・前日差","掲示板"],axis=1)
```
不要な列を削除して見易くします。
>`出力結果`
取引値	時価総額_ドル	銘柄_ティッカー	時価総額_円	一株_円
0	123.13(10:06)	2067118260000	アップル[AAPL]	225605286896400	13438.52
1	235.88(10:05)	1779057855000	マイクロソフト[MSFT]	194166374294700	25744.05
2	3102.45(10:06)	1562284437000	アマゾン・ドット・コム[AMZN]	170507723454180	338601.50
...	...	...	...	...	...
6548	3.16(10:06)	13746000	クーテック（ケイマン）[CTK]	1500238440	344.99
6549	43.00(12/09 12:15)	13599000	インターナショナル・…[ISHPB]	1484194860	4693.15
6800 rows × 5 columns

<br>
####2-10. 列の入れ替え
```python
# カラム順番の入れ替え
all_col_df6 = col_pic_df[["名称・ティッカー・市場" , "取引値" ,"一株_円" ,  "時価総額_ドル" , "時価総額_円"]] 
```
自分の好きな列順になるように調整して下さい。
>`出力結果`
名称・ティッカー・市場	取引値	一株_円	時価総額_ドル	時価総額_円
0	アップル[AAPL]	123.13(10:06)	13438.52	2067118260000	225605286896400
1	マイクロソフト[MSFT]	235.88(10:05)	25744.05	1779057855000	194166374294700
2	アマゾン・ドット・コム[AMZN]	3102.45(10:06)	338601.50	1562284437000	170507723454180
...	...	...	...	...	...
6548	クーテック（ケイマン）[CTK]	3.16(10:06)	344.99	13746000	1500238440
6549	インターナショナル・…[ISHPB]	43.00(12/09 12:15)	4693.15	13599000	1484194860
6800 rows × 5 columns

<br>
####2-11. 列要素の編集
```python
# 列順の入れ替え
# 結合するための前処理
merge_df1 = all_col_df6["名称・ティッカー・市場"]
merge_df2 = merge_df1.values.tolist()
pattern = '(?<=\[).*(?=\])'

# re.search'(?<=\[).*(?=\])'で[]の中だけを取得
# 取得した列を、元のデータフレームに結合する
re_search = [re.search(pattern, text).group() for text in merge_df2]
re_search2 = pd.DataFrame(re_search)
moto_df = all_col_df5.assign(ADR_ティッカー=re_search2)
```
列要素を結合しやすいように**アップル[AAPL]**から**AAPL**だけ抜き取ります。
列名は最終話でまとめて「ADR_ティッカー」と表示しますので、この段階で列名を変更しておきましょう。
>`出力結果`
順位	名称・ティッカー・市場	取引値	前日比・前日差	時価総額	掲示板	時価総額_ドル	時価総額_円	一株_円	ADR_ティッカー
0	1	`アップル[AAPL]` - NASDAQ	123.00(04/01 17:20)	+0.70%(+0.85)	2,064,935,808千	掲示板	2064935808000	228609043303680	13617.37	`AAPL`
1	2	`マイクロソフト[MSFT]` - NASDAQ	242.35(04/01 17:20)	+2.79%(+6.58)	1,827,855,991千	掲示板	1827855991000	202361936763610	26830.61	`MSFT`
...	...	...	...	...	...	...	...	...	...	...
6848	6849	`コナ・グリル[KONA]` - NASDAQ	0.14(04/24 20:00)	-%(---)	1,857千	掲示板	1857000	205588470	15.55	`KONA`
6849	6850	`ネフロジェネクス[NRX]` - NASDAQ	0.14(05/06 12:10)	-%(---)	1,813千	掲示板	1813000	200717230	15.56	`NRX`
6850 rows × 10 columns

<br>
#3. 検索
####3-1. 時価総額の範囲を指定
```python
all_col_df6.query
all_col_df7 = all_col_df6.query("60000000000 <= 時価総額_ドル <= 100000000000")
```
時価総額を範囲指定して、成長する見込みのある企業を検索できるようになります。
sort_values('順番に並べたい列の名前')
>`出力結果`
銘柄_ティッカー	取引値	一株_円	時価総額_ドル	時価総額_円
112	ディアジオ[DEO]	169.40(10:05)	18488.43	99091627000	10814860170780
113	アドバンスド・マイク…[AMD]	81.41(10:06)	8885.20	98613951000	10762726612140
114	アメリカン・タワー[AMT]	221.11(10:06)	24132.06	98257843000	10723860985020
...	...	...	...	...	...
201	エコラボ[ECL]	210.72(10:05)	22998.09	60234303000	6573971829420
202	UBSグループ[UBS]	15.59(10:05)	1701.60	60162674000	6566154240360
203	マーシュ・アンド・マ…[MMC]	118.37(10:05)	12919.01	60154043000	6565212253020
92 rows × 5 columns

<br>
####3-2. 一株円の価格範囲を指定
```python
all_col_df6.query
all_col_df8 = all_col_df6.query("3500 <= 一株_円 <= 10000000")
all_col_df8 = all_col_df8.sort_values('一株_円')#価格を昇降順に表示
```
時価総額をソートした時とやり方は同じです。
>`出力結果`
銘柄_ティッカー	取引値	一株_円	時価総額_ドル	時価総額_円
818	AXAエクイタブル・ホー…[EQH]	32.10(10:05)	3503.50	13980985000	1525884702900
3090	トライマス[TRS]	32.16(10:02)	3510.05	1388610000	151552895400
1223	テソロ・ロジスティッ…[ANDX]	32.17(07/29 16:15)	3511.11	7901931000	862416749340
...	...	...	...	...	...
115	ブッキング・ホールデ…[BKNG]	2398.05(10:06)	261723.29	98228435000	10720651395900
2	アマゾン・ドット・コム[AMZN]	3102.45(10:06)	338601.50	1562284437000	170507723454180
718	NVR[NVR]
2462 rows × 5 columns

<br>
#4. 終わりに
次回、[第二話](https://qiita.com/seaoto/items/3385e56274b4e537ea25)からはADR銘柄の取得をしていきます。
最後まで読んで頂きありがとうございました。
まだまだ初学者ですので、もっと良い記述の方法があればご指摘お願い致します！