AIとファイナンス

AIとファイナンスの架け橋、それがこのブログの目指すところです。兼業投資家向けに、Pythonを駆使して株やFXの分析を「自分で」行えるようになるための情報を提供します。ニューラルネットワークを活用した市場予測から、実証済みの金融理論まで、全てのコードを公開し、誰もが活用できるように!是非色々なコードで遊んでみてください!

【米国株】IPO企業の株価変動分析。テンバガー銘柄を探せ!【Python】

こんにちは、前回の記事ではここ米国市場でこの5年間でIPOした企業のリストをダウンロードすることに成功しました。今回はこのリストを元に株価をダウンロードして何か有益な情報を得られないか見てみましょう!前提として前回の記事で作成した「ipo_df」の中に入っているティッカーの株価をダウンロードしていきます。最下段に前回のものを含めたコードを書いておきますので皆さまも是非試してみてください!

データの準備

yfinanceを使用して、各ティッカーの株価データをダウンロードします。

import pandas as pd
import yfinance as yf

# 各ティッカーの株価データをダウンロードし、正規化してDataFrameに追加
for index, row in ipo_df.iterrows():
    ticker = row['ticker']
    ipo_date = row['ipo_date']
    stock = yf.Ticker(ticker)
    # IPO日から1年後までのデータを取得
    hist = stock.history(start=ipo_date, end=pd.to_datetime(ipo_date) + pd.DateOffset(years=1))
 

正規化

上場日の終値を基準にして、1年間の終値を正規化します。

    # 上場日の終値を基準に正規化
    if not hist.empty and 'Close' in hist:
        base_price = hist.iloc[0]['Close']
        normalized_close = hist['Close'] / base_price

DataFrameへの追加

正規化した終値ipo_dfに新しい列として追加します。

        # 正規化した終値ipo_dfに追加
        for i, value in enumerate(normalized_close):
            column_name = f'Normalized Close {i}'
            if column_name not in ipo_df:
                ipo_df[column_name] = None  # 新しい列をNoneで初期化
            ipo_df.at[index, column_name] = value

結果

データの視覚化

さて、上の表のようにデータを集めることができました!そうしたら次はもちろん視覚化ですよね!今回のデータの中には100倍超になったものもありましたがかなりレアなケースなので今回は0から15倍までを視覚化してみます。

# 正規化した株価が0-15までの範囲を全て重ね合わせてプロット
plt.figure(figsize=(14, 8))

# 日数ごとの正規化された終値をプロット
for index, row in ipo_df.iterrows():
    normalized_prices = row[4:].values  # 'ticker', 'ipo_date', 'name', 'ipo_price'を除いた正規化された株価を取得
    days_since_ipo = range(len(normalized_prices))
    plt.plot(days_since_ipo, normalized_prices, label=row['ticker'])

# 株価1倍の線を濃い緑色の太めの線で表示
plt.axhline(y=1, color='darkgreen', linestyle='-', linewidth=2, label='Stock Price 1x')

plt.title('Normalized Stock Prices After IPO (0-15 Range)')
plt.xlabel('Days Since IPO')
plt.ylabel('Normalized Stock Price')
plt.ylim(0, 15)  # Y軸の範囲を0から15に設定
#plt.legend()
plt.show()

結果

結果はご覧の通り!これだけではパット見ると上場一年以内に一度でもテンバガーしているのがわずかに三社しかないというのが視覚的にも分かりますね!見たところ倒産したり低迷しているものはたくさんありますが倍以上になっているものもかなりありそうです。次回はこれらをもう少し深く分析していきましょう!

是非クリックお願いします!

 

import requests
import pandas as pd
from bs4 import BeautifulSoup
import re
from datetime import datetime
import yfinance as yf
import matplotlib.pyplot as plt

current_year = datetime.now().year  # 現在の年を取得
data = []  # スクレイピングしたデータを保存するリスト

while True:
    url = f'https://stockanalysis.com/ipos/{current_year}/'
    response = requests.get(url)
    soup = BeautifulSoup(response.content, 'html.parser')

    # ページが存在しない場合、ループを終了
    if response.status_code != 200:
        break
   
    # 'const data'が含まれているスクリプトタグを探す
    # DeprecationWarningを避けるために'string'を使用
    script = soup.find('script', string=lambda t: t and 'const data' in t)

    # スクリプトタグからデータ部分を抽出
    data_str = script.string.split('const data = ')[1].split(';')[0]

    # 正規表現を使用して、必要なデータを抽出
    pattern = r'\{s:"(?P<ticker>[^"]+)",ipoDate:"(?P<ipo_date>[^"]+)",n:"(?P<name>[^"]+)",ipoPrice:(?P<ipo_price>\d+\.?\d*)'
    matches = re.finditer(pattern, data_str)

    # 抽出したデータをリストに格納
    for match in matches:
      data.append(match.groupdict())
   
    current_year -= 1  # 次のループで前年のデータをチェック

# 最後に、全てのデータをDataFrameに変換し、CSVファイルとして保存
ipo_df = pd.DataFrame(data)
ipo_df.to_csv('ipo_data.csv', index=False)

# 各ティッカーの株価データをダウンロードし、正規化してDataFrameに追加
for index, row in ipo_df.iterrows():
    ticker = row['ticker']
    ipo_date = row['ipo_date']
    stock = yf.Ticker(ticker)
    # IPO日から1年後までのデータを取得
    hist = stock.history(start=ipo_date, end=pd.to_datetime(ipo_date) + pd.DateOffset(years=1))
   
    # 上場日の終値を基準に正規化
    if not hist.empty and 'Close' in hist:
        base_price = hist.iloc[0]['Close']
        normalized_close = hist['Close'] / base_price
       
        # 正規化した終値ipo_dfに追加
        for i, value in enumerate(normalized_close):
            column_name = f'Normalized Close {i}'
            if column_name not in ipo_df:
                ipo_df[column_name] = None  # 新しい列をNoneで初期化
            ipo_df.at[index, column_name] = value
 
# 正規化した株価が0-15までの範囲を全て重ね合わせてプロット
plt.figure(figsize=(14, 8))

# 日数ごとの正規化された終値をプロット
for index, row in ipo_df.iterrows():
    normalized_prices = row[4:].values  # 'ticker', 'ipo_date', 'name', 'ipo_price'を除いた正規化された株価を取得
    days_since_ipo = range(len(normalized_prices))
    plt.plot(days_since_ipo, normalized_prices, label=row['ticker'])

# 株価1倍の線を濃い緑色の太めの線で表示
plt.axhline(y=1, color='darkgreen', linestyle='-', linewidth=2, label='Stock Price 1x')

plt.title('Normalized Stock Prices After IPO (0-15 Range)')
plt.xlabel('Days Since IPO')
plt.ylabel('Normalized Stock Price')
plt.ylim(0, 15)  # Y軸の範囲を0から15に設定
#plt.legend()
plt.show()