Google Colabで株価分析|日本語フォントとUTC問題の解決

環境構築なし・無料で株価分析を始める 準備・環境構築

本記事はPython学習・情報提供を目的としています。投資判断はご自身の責任で行ってください。

「Pythonで株価分析を始めたいけど、環境構築でつまずいた」という話をよく聞きます。Windowsのパスが通らない、pipがexternally-managed-environmentで怒る、matplotlibで日本語が豆腐になる。始める前に力尽きます。

その全部を飛ばせるのがGoogle Colabです。ブラウザだけで動き、pandasもnumpyも最初から入っています。

ただし、ColabにはColab特有の詰まりどころがあります。日本語フォントが出ない、タイムゾーンがUTCなので「今日」がずれる、90分放置で全部消える。この記事では始め方に加えて、そこを先回りして潰します。

📘 外部参考Google Colab FAQ(公式・日本語)yfinance 公式GitHub

Google Colabとは

Google Colaboratory(Colab)は、Googleが提供するクラウド上のJupyterノートブック環境です。ブラウザだけで動き、Pythonのインストールは不要。Googleアカウントがあればすぐ使えます。

colab.research.google.com にアクセスして「新しいノートブック」をクリックするだけです。

項目内容
✅ 環境構築不要pandas・numpy・matplotlibは導入済み
✅ 無料株価分析の範囲なら無料枠で十分
✅ Drive連携CSVやモデルの保存が簡単
✅ 共有が簡単URLで分析ノートを共有できる
⚠️ 90分ルール操作しないと約90分で切断
⚠️ 12時間ルール連続実行は最大約12時間でリセット
⚠️ タイムゾーンランタイムはUTC。日本時間ではない
⚠️ 日本語初期状態ではグラフの日本語が文字化けする

最初のセルに書いておくべきこと

新しいノートブックを作ったら、まずこれを1つ目のセルに貼ってください。日本語フォント・タイムゾーン・ライブラリを一度に片付けます。

# === 初期セットアップ(ノートブックの先頭に置く)===
!pip install -q yfinance==0.2.* mplfinance
!apt-get install -y -qq fonts-ipaexfont > /dev/null

import matplotlib
import matplotlib.pyplot as plt
from matplotlib import font_manager

# インストールしたフォントをmatplotlibに認識させる
for f in font_manager.findSystemFonts(fontpaths=["/usr/share/fonts"]):
    if "ipaexg" in f.lower():
        font_manager.fontManager.addfont(f)
matplotlib.rcParams["font.family"] = "IPAexGothic"
matplotlib.rcParams["axes.unicode_minus"] = False   # マイナス記号の化け対策

# ランタイムはUTC。日本時間を明示的に扱う
import os, time
os.environ["TZ"] = "Asia/Tokyo"
time.tzset()

plt.plot([1, 2, 3]); plt.title("日本語テスト:日経平均"); plt.show()
print("セットアップ完了")

axes.unicode_minus = Falseを忘れると、日本語フォントを設定した途端にマイナス記号だけが豆腐になります。リターンのグラフでこれをやると悲惨です。

また、pip installのあとに「ランタイムを再起動してください」と表示されることがあります。numpyなど基幹ライブラリのバージョンが変わったときです。その場合は必ず再起動してから続けてください。無視すると、あとから謎のインポートエラーに悩まされます。

タイムゾーンの罠

ColabのランタイムはUTCで動いています。日本時間より9時間遅れです。日本の朝9時はUTCの深夜0時。つまり、日本の午前中にdatetime.now()を呼ぶと、前日の日付が返ってきます。

import datetime as dt
from zoneinfo import ZoneInfo

JST = ZoneInfo("Asia/Tokyo")

def today_jst() -> dt.date:
    return dt.datetime.now(tz=JST).date()

def market_open_jst() -> bool:
    now = dt.datetime.now(tz=JST)
    if now.weekday() >= 5:
        return False
    t = now.time()
    return (dt.time(9, 0) <= t <= dt.time(11, 30)) or \
           (dt.time(12, 30) <= t <= dt.time(15, 30))

print("UTCの今日:", dt.datetime.utcnow().date())
print("日本の今日:", today_jst())
print("ザラ場中?:", market_open_jst())

「昨日までのデータを取得」という処理をUTCの日付で書くと、日本時間の午前中は一昨日までのデータになります。バックテストの期間指定でこれをやると、原因不明のズレとして数時間溶かします。ZoneInfoで明示するのが確実です。

株価データを取得する

import numpy as np
import pandas as pd
import yfinance as yf

def fetch(ticker: str, period: str = "1y") -> pd.DataFrame:
    df = yf.download(ticker, period=period, auto_adjust=True, progress=False)
    if df.empty:
        raise RuntimeError(f"{ticker}: データが取得できません")
    if isinstance(df.columns, pd.MultiIndex):     # 複数銘柄形式で返ることがある
        df.columns = df.columns.get_level_values(0)
    return df

df = fetch("^N225", "3mo")

fig, ax = plt.subplots(figsize=(12, 5))
ax.plot(df.index, df["Close"], color="steelblue", lw=1.2, label="日経平均")
ax.set_title("日経平均株価(直近3ヶ月)")
ax.set_ylabel("終値(円)")
ax.grid(alpha=0.3); ax.legend()
plt.tight_layout(); plt.show()

print(f"最新終値: {df['Close'].iloc[-1]:,.0f}円")

auto_adjust=Trueを明示しています。株式分割の影響を除いた価格になるので、過去チャートに不自然な段差が出ません。

複数銘柄を一括で比較する

NAMES = {"7203.T": "トヨタ", "6758.T": "ソニーG",
         "9984.T": "ソフトバンクG", "8306.T": "三菱UFJ"}

# 1銘柄ずつループするより、まとめて1回で取得したほうが速い
raw = yf.download(list(NAMES), period="1y", auto_adjust=True,
                  progress=False, group_by="column")["Close"]
raw = raw.rename(columns=NAMES).dropna(how="all")

summary = pd.DataFrame({
    "1ヶ月": raw.pct_change(21).iloc[-1] * 100,
    "3ヶ月": raw.pct_change(63).iloc[-1] * 100,
    "1年": raw.pct_change(252).iloc[-1] * 100,
    "年率ボラ": raw.pct_change().std() * np.sqrt(252) * 100,
}).round(1).sort_values("1年", ascending=False)

display(summary)   # Colabなら display() で表がきれいに出る

ループで1銘柄ずつyf.Ticker().history()を呼ぶ書き方をよく見ますが、銘柄数が増えるとレート制限に当たります。まとめて1回で取るのが基本です。

また、Colabではprint()よりdisplay()のほうがDataFrameがきれいに表示されます。セルの最終行に変数名を書くだけでも同じです。

APIキーを安全に扱う

ノートブックを共有すると中身がそのまま見えます。APIキーをコードに直接書くと、共有した瞬間に漏洩します。ColabにはSecrets機能があるので、必ずこちらを使ってください。

左サイドバーの鍵アイコンから「新しいシークレットを追加」で名前と値を登録し、そのノートブックへのアクセスを有効にします。

from google.colab import userdata

def get_secret(name: str) -> str:
    try:
        return userdata.get(name)
    except Exception:
        raise RuntimeError(
            f"シークレット '{name}' が未設定です。"
            "左の鍵アイコンから登録し、このノートブックへのアクセスを許可してください"
        )

JQUANTS_KEY = get_secret("JQUANTS_API_KEY")
print("キーの読み込みに成功しました(長さ:", len(JQUANTS_KEY), ")")

シークレットはGoogleアカウントに紐づくので、ノートブックを共有しても値は渡りません。共有相手は自分のキーを登録して使います。

セッションが消える前提で書く

Colabは90分操作しないと切断され、連続実行も約12時間でリセットされます。メモリ上の変数は全部消えます。数分で終わる分析なら問題ありませんが、大量のデータを集めるときは途中結果を残す設計にします。

from google.colab import drive
from pathlib import Path

drive.mount("/content/drive")
CACHE = Path("/content/drive/MyDrive/stock_cache")
CACHE.mkdir(parents=True, exist_ok=True)

def cached_fetch(ticker: str, period: str = "5y") -> pd.DataFrame:
    """Driveにキャッシュして、切断後も取得済みデータを無駄にしない。"""
    path = CACHE / f"{ticker.replace('.', '_')}_{period}.parquet"
    if path.exists():
        return pd.read_parquet(path)
    df = fetch(ticker, period)
    df.to_parquet(path)
    return df

def fetch_many(tickers: list[str]) -> dict:
    out = {}
    for i, t in enumerate(tickers, 1):
        try:
            out[t] = cached_fetch(t)
            print(f"[{i}/{len(tickers)}] {t} ok")
        except Exception as e:
            print(f"[{i}/{len(tickers)}] {t} 失敗: {e}")
    return out

CSVではなくParquetにしているのは、型(日付やfloat)がそのまま保存され、読み書きも速いからです。CSVだと読み直すたびに日付が文字列になって、毎回pd.to_datetime()を書くはめになります。

GPUは切っておく

「無料でGPUが使える」がColabの売りですが、株価分析でGPUが要る場面はほとんどありません。pandasもyfinanceもCPUで動きます。

それどころか、GPUランタイムを選ぶとGPUの利用枠を無駄に消費します。無料枠のGPU時間は混雑状況で変動するため、本当に必要なとき(LSTMの学習など)に割り当てが来なくなります。

「ランタイム → ランタイムのタイプを変更」でハードウェアアクセラレータを「None」にしておきましょう。起動も速くなります。

Colabでやってはいけないこと

自動売買BOTの常時稼働には使えません。これは制限の話ではなく、設計上そうなっています。

  • 90分操作しないと切断されるので、無人運用が成立しない
  • 連続実行も最大12時間でリセットされる
  • 切断時にポジションを持っていても、後始末のコードは走らない
  • ブラウザを閉じると(Pro+のバックグラウンド実行を除き)止まる

ブラウザを自動クリックさせて切断を回避する裏技が出回っていますが、利用規約に抵触する可能性があるうえ、実弾を扱うシステムを「切れるかもしれない環境」で動かすこと自体が危険です。定時実行にはGitHub Actions、常時稼働にはVPSを使ってください。

用途適した環境
学習・試行錯誤・可視化Google Colab
1日1回のスクリーニング通知GitHub Actions(無料)
ザラ場中の常時監視・自動売買VPSまたは自宅PC常時稼働
重いモデルの学習Colab Pro+ または クラウドGPU

有料プランを検討する基準

プラン月額(日本)連続実行バックグラウンド
無料¥0最大約12時間不可
Colab Pro約¥1,179最大約24時間不可
Colab Pro+約¥5,767長時間可能

Pro以上はコンピューティングユニット(CU)を消費する方式です。CUを使い切ると、月額を払っていてもランタイムが終了します。逆に、CPUだけの株価分析ならCUの消費はごくわずかです。

判断基準はシンプルで、「GPUで学習を回すか」だけです。pandasでバックテストを書いているうちは、無料枠で困りません。

まとめ

  • 先頭セルでフォント・タイムゾーン・ライブラリをまとめて設定する
  • axes.unicode_minus = Falseを忘れない(マイナス記号が化ける)
  • ランタイムはUTC。日付はZoneInfo("Asia/Tokyo")で明示する
  • APIキーはColab Secretsに置く。コードに書かない
  • 時間のかかる取得はDriveにParquetでキャッシュする
  • GPUは使わないなら「None」にして枠を温存する
  • 自動売買の常時稼働には使わない。GitHub ActionsかVPSへ

Colabは「試す」ための環境として非常に優秀です。まずはここで手を動かして、動くコードができてから、それを動かし続ける場所を考える。この順番が結局いちばん早く進みます。

タイトルとURLをコピーしました