見出し画像

米株Python [3-5] Finvizスクリーニング

こんにちわ!トミィ(@toushi_tommy)です!前回YahooFinanceでのスクリーニング結果を出力する方法を紹介いたしましたが、今回はFinvizでのスクリーニングを出力させてみます。こちらの方がよりパワフルなスクリーニングが出来るように思えます。一度、スクリーニング出力設定を作ってしまうと、次回からはFinvizにアクセスせずに、pythonを実行するだけで表で出力することができます。また有料部分ではありますが、日本の証券会社(楽天証券)で買える商品に絞って出力させることもできますので、是非確認してみてください。(追記:有料部分に、スクリーニング結果をチャートサマリで見ることができるようにコード追加しました)

サークルは無料で運営しております。記事内容も無料です。トミィにジュースでもおごってあげようと思った方は投げ銭いただけると、今後の運営の励みになります。(楽天証券で購入できる銘柄リストへの絞り方コードのみ有料記事にしておりますので、下記をご覧ください。さらにスクリーニング結果をチャートで出力するコードも追記しました)

Finvizでの米国株スクリーニング

ヒートマップで有名なFinvizのサイトはこちらになります。

Finvizと言えば、毎日、毎月などのヒートマップですが、上記のページにアクセスし「Maps」を押すとよく見るこんな画面にになります。

画像1

実は、ヒートマップのみでなく、強力なスクリーニング機能があります。「Maps」ボタンの左にある「Screener」を押してみてください。このような画面になると思います。

画像2

このフィルター機能を使って、好きな条件で銘柄を探すことができるのですが、まさに色んな項目があります。まず、非常に簡単なスクリーニングですが、Signalメニューのドロップダウンメニューを使います。

画像3

例えば、この中から「Top Gainers」を選ぶと昨日の値上がりトップ銘柄が出力されます。いろいろ試してみてください。pythonで出力するには、この時に表示されるURLを使います。これを選んだ時のURLはこんな感じになると思います。

https://finviz.com/screener.ashx?v=111&s=ta_topgainers

このように、自分が見たいスクリーニングのURLを作ってください。さらにパワフルなスクリーニングですが、Signalメニューの下の「Descriptive」「Fundamental」「Technical」「All」から自分が好きな条件を作ってください。

画像4

スクリーニング結果のpython出力

それでは、作ったスクリーニング条件を元にpythonで出力してみます。まずは、先ほどの値上がりトップ銘柄を出力してみます。コードはこちらになります。

##############################################
output_dir = '/content/drive/MyDrive/output/'
font_dir   = '/content/drive/MyDrive/fonts/'
##############################################

from bs4 import BeautifulSoup
import re
import requests
import pandas as pd

# URL ###################################################
# TOP GAIN
url = 'https://finviz.com/screener.ashx?v=111&s=ta_topgainers'
#########################################################

site = requests.get(url, headers={'User-Agent': 'Custom'})
data = BeautifulSoup(site.text,'html.parser')

da = data.find_all("tr", align="center")
tables = re.findall('<td class="table-top.*</td>', str(da[0]))
names = [re.sub('.*>(.+)</td>.*', r'\1', s) for s in tables]
cntns = re.findall('<a class="screener-link.*</a>', str(da[0]))
contents = [[re.sub('<a .*">(.+)</a>.*', r'\1', s).replace('</span>','').replace('&amp;','&') for s in re.findall('<a .*?</a>', i)] for i in cntns]
df = pd.DataFrame(contents, columns = names)

######################################################
# 表出力
######################################################
from PIL import Image, ImageDraw, ImageFont
import IPython
import os
######################################################
def xycenter(xp, yp, xw, yw, tx, fn):
 x,y = draw.textsize(tx,fn)
 return xp+(xw-x)/2, yp+(yw-y)/2
######################################################
def adjust_font(txt_data, check_width, fnt_name, max_size):
 tmp_font = ImageFont.truetype(fnt_name, max_size)
 x_size = draw.textsize(txt_data,tmp_font)[0]
 while (check_width-5)<x_size:
   max_size-=1
   tmp_font = ImageFont.truetype(fnt_name, max_size)
   x_size = draw.textsize(txt_data,tmp_font)[0]
 return tmp_font
######################################################
jap_font = '/content/drive/MyDrive/module/japanize_matplotlib/fonts/ipaexg.ttf'
japb_font = '/content/drive/MyDrive/module/japanize_matplotlib/fonts/ipaexg.ttf'
jap2_font = font_dir+'meiryo.ttc'
jap2b_font = font_dir+'meiryob.ttc'
if os.path.exists(jap2_font): jap_font = jap2_font
if os.path.exists(jap2b_font): japb_font = jap2b_font
######################################################
# 表の幅を設定
max_font = 14
y_height_hd = 30 # ヘッダ用 縦サイズ
y_height = 30 # 縦サイズ
color_cel = ["Change"] # 出力時に数字に応じて色付け
x_width = {
 "No." :40,"Ticker" :80,"Company" :250,
 "Sector" :150,"Industry" :200,"Country" :90,"Market Cap" :90,
 "P/E" :80,"Price" :80,"Change" :80,"Volume" :120
}
x_default = 80

x_start = 10
y_start = 10
######################################################

x_sum=0
for i in df.columns.to_list():
 x_width[i]=x_default if i not in x_width else x_width[i]
 x_sum+=x_width[i]
######################################################

im = Image.new('RGB', (x_sum+20, y_height_hd+(len(df))*y_height+20), 'white')
draw = ImageDraw.Draw(im)

outfile = output_dir+'out.png'

xpos = x_start
ypos = y_start

# ヘッダ出力 #####
font_head=ImageFont.truetype(japb_font, max_font)
for i in df.columns.to_list():
 draw.rectangle([(xpos, ypos), (xpos+x_width[i], ypos+y_height_hd)], fill=(247, 203, 77), outline=(0,0,0),  width=1)
 font_head=adjust_font(i,x_width[i],japb_font,max_font)
 draw.text((xycenter(xpos,ypos,x_width[i],y_height_hd,i,font_head)),i, (0,0,0),font=font_head)
 xpos+=x_width[i]

# データ出力 ####
font_txt=ImageFont.truetype(jap_font, max_font)
ypos+=y_height_hd
for i in range(len(df)):
 xpos = x_start
 draw.rectangle([(xpos, ypos), (xpos+x_sum, ypos+y_height)], outline=(0,0,0),  width=1
   , fill=((255,255,255) if i%2 == 0 else (254, 248, 227)))

 # データ ####
 for j in df.columns.to_list():
   font_txt=adjust_font(str(df[j][i]),x_width[j],jap_font,max_font)
   draw.rectangle([(xpos, ypos), (xpos+x_width[j], ypos+y_height)], outline=(0,0,0),  width=1)
   txt_color = (0,0,0) if j not in color_cel else 'red' if str(df[j][i])[:1]=='-' else 'blue'
   draw.text((xycenter(xpos,ypos,x_width[j],y_height,str(df[j][i]),font_txt)),str(df[j][i]), txt_color,font=font_txt)
   xpos+=x_width[j]
 ypos+=y_height

######################################################
# 枠線
draw.rectangle([(x_start, y_start), (xpos, y_start+y_height_hd)], outline='black', width=3)
draw.rectangle([(x_start, y_start), (xpos, ypos)], outline='black', width=3)

im.save(outfile)
IPython.display.Image(outfile)

出力はこのような結果になります。

画像5

こちらの部分を変更することで、Finvizにアクセスせずに、簡単にスクリーニング結果を見ることができると思いますので、ご活用ください。

# URL ###################################################
# TOP GAIN
url = 'https://finviz.com/screener.ashx?v=111&s=ta_topgainers'
#########################################################

課題:

新高値を更新した成長・中小型株を出力してみましょう。また、色んな条件を試して出力してみましょう。

例)

画像6

url = 'https://finviz.com/screener.ashx?v=111&s=ta_newhigh&f=cap_midunder,fa_epsyoy1_o25,fa_salesqoq_o25&ft=4'

楽天証券で購入できる銘柄に絞る方法

以下、ジュースをおごっていただいた方のみ、コードを公開しております。値上がり率ランキングの場合はこのような出力になります。(実際買える銘柄になるとかなり減りますね・・・)

画像7

さらに、スクリーニング結果をチャートで出力するコードも追記しました。このような出力結果になります。(一番最後のコードです)

画像9

以下、コード部分です。


ここから先は

22,638字 / 1画像

¥ 150

サポートいただけますと、うれしいです。より良い記事を書く励みになります!