OANDA Tick データ自動ダウンロードバッチを構築した話

OANDA Tick データ自動ダウンロードバッチを構築した話

作成日:
更新日:

「また今月もダウンロード忘れてた...」

これ、めちゃくちゃストレスだったんですよね。

FXのトレード分析をするために、OANDAからTickデータをダウンロードする作業。毎月1日にログインして、5つの銘柄を1つずつポチポチとダウンロード。単純作業なのに、忘れると過去のデータは取れないし、かといって覚えておくのも面倒。

「これ、絶対に自動化できるでしょ!」

というわけで、Seleniumを使って完全自動化のバッチを作りました。もう二度と手動でダウンロードすることはありません。

なぜ自動化が必要だったのか

FXの分析をするには、高品質なTickデータが必要です。OANDAは無料でTickデータを提供してくれる素晴らしいサービスなんですが、1つだけ問題がありました。

ダウンロードが手動なんです。

しかも、対象銘柄は5つ:

  • USDJPY (ドル円)
  • EURJPY (ユーロ円)
  • EURUSD (ユーロドル)
  • JP225 (日経225)
  • US500 (S&P500)

毎月1日に、ログインして、銘柄を選んで、年月を選んで、ダウンロードボタンを押して...これを5回繰り返す。

1回あたり2分としても、年間で2時間以上をこの単純作業に費やすことになります。

さらに最悪なのが、ダウンロード忘れです。過去のデータは後から取れないので、1ヶ月分を逃すと、分析に穴が空いてしまいます。

「エンジニアなんだから、自動化しようよ」と自分に言い聞かせ、重い腰を上げました。

技術選定:なぜSeleniumなのか

最初は「APIがあるでしょ」と思ったんですが、OANDAのTickデータダウンロードはWeb画面からしかできないんです。

つまり、選択肢は2つ:

  1. 手動で頑張る → 却下
  2. ブラウザ操作を自動化 → これしかない!

ということで、Seleniumを採用しました。

Seleniumを選んだ理由:

  • ブラウザを完全に制御できる
  • ヘッドレスモード(画面なし)で実行可能
  • Pythonとの相性が良い
  • サーバーでの自動実行が簡単

あと、今回はuvという高速なPythonパッケージマネージャーも試してみました。これがまた便利で、pipより圧倒的に速いんです。

環境構築:uvが速すぎて驚いた

まずは開発環境の準備です。今回、初めてuvを使ってみたんですが、これがマジで速い!

# uvで仮想環境を作成(一瞬で終わる)
cd /path/to/fx
uv venv --python 3.12
source .venv/bin/activate

# パッケージのインストールも爆速
uv pip install -r requirements.txt

pipだと10秒くらいかかってたのが、uvだと3秒とかで終わります。これからはuvを使おう、と心に決めました。

必要なライブラリは以下の3つだけ:

  • Selenium: ブラウザ自動操作の本命
  • webdriver-manager: ChromeDriverを自動で用意してくれる便利ツール
  • python-dotenv: パスワードをコードに書きたくないので

認証情報は.envファイルで管理:

OANDA_EMAIL=your_email@example.com
OANDA_PASSWORD=your_password

DOWNLOAD_DIR=/path/to/data/oanda_fx
LOG_DIR=/path/to/logs

パスワードをGitにコミットしてしまう事故を防ぐため、.gitignore.envを追加するのを忘れずに!

実装で工夫したポイント

さて、ここからが本番です。実装で特に工夫した点を紹介します。

1. ヘッドレス実行で完全自動化

最大のポイントは、画面なしで動かすことです。

サーバーで自動実行するので、ブラウザのウィンドウが開いたら困ります。Seleniumのヘッドレスモードを使えば、画面を表示せずにブラウザを操作できます。

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

options = Options()
options.add_argument('--headless')        # 画面を表示しない
options.add_argument('--no-sandbox')      # サンドボックスを無効化
options.add_argument('--disable-dev-shm-usage')  # メモリ不足対策

driver = webdriver.Chrome(options=options)

この3つのオプションは、特にLinuxサーバーで動かすときに必須です。これがないと、謎のエラーで動かないことが多いんですよね...(何度ハマったことか)

2. ZIP自動解凍で手間を省く

OANDAからダウンロードしたファイルは、ZIPで圧縮されています。手動なら「ダブルクリックして解凍」で済むんですが、自動化するとなると話は別。

Pythonの標準ライブラリzipfileで、ダウンロード後に自動で解凍します:

import zipfile

def extract_zip(zip_path):
    """ZIPファイルを解凍してCSVを取得"""
    with zipfile.ZipFile(zip_path, 'r') as zip_ref:
        zip_ref.extractall(zip_path.parent)

これで、「気づいたらCSVファイルが並んでいる」という理想の状態に。

3. 重複ダウンロードを防ぐ

何度も同じファイルをダウンロードするのは無駄なので、既存ファイルのチェックを入れました:

csv_path = download_dir / f"ticks_{instrument}-oj5k_{year}-{month:02d}.csv"
if csv_path.exists():
    logging.info(f"{csv_path} は既に存在します。スキップします。")
    return

これがあると、途中で失敗しても、再実行時に成功した部分はスキップされます。5つの銘柄のうち3つまで成功した状態で落ちても、次は残り2つだけダウンロードすればOK。

地味だけど、めちゃくちゃ便利な機能です。

4. ログで何が起きたか把握する

自動化の怖いところは、失敗に気づかないことです。

「先月のデータ、ダウンロードできてなかった...」とか、1ヶ月後に気づいたら最悪ですよね。

なので、詳細なログを残すようにしました:

import logging

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler('logs/oanda_download.log'),  # ファイルにも
        logging.StreamHandler()  # 画面にも
    ]
)

これで、「いつ、何が起きたか」が全部記録されます。

実際のログはこんな感じ:

2025-11-13 03:00:05 - INFO - OANDAに自動ログイン中...
2025-11-13 03:00:12 - INFO - USD_JPY 2024年10月のダウンロード開始
2025-11-13 03:00:28 - INFO - ダウンロード完了: ticks_USD_JPY-oj5k_2024-10.csv
2025-11-13 03:00:29 - INFO - EUR_JPY 2024年10月のダウンロード開始
...

朝起きて、ログを見て「よし、ちゃんと動いてる!」って確認できるのは、精神衛生上とても良いです。

使い方:柔軟に対応できるように

作ったからには、使いやすくないと意味がありません。いくつかの実行モードを用意しました。

基本的な使い方

一番シンプルなのは、引数なしで実行する方法。これで前月のデータが自動でダウンロードされます:

python src/batch/oanda_tick_downloader.py

これだけ。簡単でしょ?

過去のデータを取りたいとき

「去年の12月のデータが欲しい」みたいな時もあります。そんな時は、年月を指定できます:

# 2024年12月のデータをダウンロード
python src/batch/oanda_tick_downloader.py --year 2024 --month 12

これで、過去データも自由に取得可能。

デバッグモード:動作確認が捗る

開発中、「ちゃんと動いてるのか?」を確認したいときってありますよね。

ヘッドレスモードだと画面が見えないので、デバッグが難しい...そんな時のために、ブラウザ表示モードも用意しました:

python src/batch/oanda_tick_downloader.py --no-headless

これで、Chromeのウィンドウが開いて、実際の動作が見られます。「あ、ここでクリックに失敗してるのか」とか、一目瞭然。

開発の初期段階では、このモードで何度も動作確認しました。

テストスクリプトで段階的にテスト

いきなり全機能をテストするのは怖いので、段階的にテストできるスクリプトも作りました:

# ログインだけテスト(一番最初に確認)
python src/batch/test_download.py login

# 1つの銘柄だけダウンロード(動作確認)
python src/batch/test_download.py single

# 全銘柄ダウンロード(最終確認)
python src/batch/test_download.py full

特にloginテストは便利で、「パスワード間違ってないか?」とか、「ログイン画面の構造変わってないか?」をサクッと確認できます。

cronで完全自動化:もう忘れない

さて、ここからが本番です。毎月1日の午前3時に、自動でダウンロードされるように設定します。

cronの設定はシンプル:

# crontabを編集
crontab -e

# 以下を追加
0 3 1 * * cd /path/to/fx && /path/to/.venv/bin/python src/batch/oanda_tick_downloader.py >> logs/cron.log 2>&1

この設定で、毎月1日の午前3時に自動実行されます。

なぜ午前3時なのか?それは:

  1. OANDAのサーバーが空いている時間帯: 日本時間の早朝は比較的軽い
  2. 自分が寝ている時間: 起きてる時間にサーバーの負荷をかけたくない
  3. 朝起きたら完了している: 「今月もちゃんと取れたな」って確認できる

これで、完全放置で毎月データが溜まっていくシステムの完成です!

ハマったポイント:トラブルシューティング

開発中、いくつかハマったポイントがあったので、共有します。

ChromeDriverが見つからない問題

最初、ChromeDriverのパスが通ってなくてエラーになりました。

selenium.common.exceptions.WebDriverException: Message: 'chromedriver' executable needs to be in PATH.

これ、初心者あるあるですよね。

解決策は、webdriver-managerを使うこと。これを使えば、ChromeDriverを自動でダウンロード&管理してくれます:

uv pip install webdriver-manager

もしそれでもダメなら、アップデートしてみてください:

pip install --upgrade webdriver-manager

Ubuntuサーバーでヘッドレス実行が動かない

ローカル(Mac)では動いたのに、Ubuntuサーバーに持っていったら動かない...これもハマりました。

原因は、Chromeがインストールされていないこと。サーバーにはデフォルトでブラウザが入ってないんですよね。

# Chrome/Chromium をインストール
sudo apt update
sudo apt install -y chromium-browser chromium-chromedriver

これで解決。ヘッドレスモードでも、実はChromeの実体が必要なんです。

ログイン失敗:パスワードが通らない

「パスワード合ってるはずなのに、ログインできない!」

焦りました。何度確認しても、間違ってない。

原因は、二段階認証でした。OANDAのアカウントで二段階認証を有効にしていると、Seleniumでのログインが失敗します。

対処法:

  1. 二段階認証を一時的に無効化する
  2. または、アプリケーション専用のパスワードを発行する

私は二段階認証を無効にしました(セキュリティとのトレードオフですが、このアカウントは分析専用なので許容)。

デバッグのコツは、--no-headlessでブラウザを表示させて、実際の動きを見ること。これで大抵の問題は分かります。

自動化して変わったこと

このバッチを動かし始めて、1ヶ月が経ちました。人生が変わりました。

時間が浮いた

毎月10分×12ヶ月=年間2時間の節約。たった2時間と思うかもしれませんが、精神的な負担が消えたのが大きい。

「ダウンロード忘れてないかな...」という不安がゼロになりました。

データが確実に溜まる

人間は忘れるけど、プログラムは忘れません。毎月1日の午前3時、確実にデータが取得されます。

気づいたら、3ヶ月分、半年分とデータが溜まっていく。これ、めちゃくちゃ気持ちいいです。

分析に集中できる

「データを集める」という作業から解放されて、「データを分析する」ことに集中できるようになりました。

これが一番大きい。エンジニアは、本質的な作業に時間を使うべきです。

今後の展開:ここからが本番

データ収集の自動化は、あくまでスタート地点です。

ここから、やりたいことはたくさんあります:

1. データ分析の本格化

溜まったTickデータを使って、相場の分析をします。

  • 時間帯ごとのボラティリティ
  • 通貨ペア間の相関関係
  • 季節性の分析

など、面白いことが見えてくるはず。

2. テクニカル指標の計算

移動平均、ボリンジャーバンド、RSI...などなど。

Pythonのpandasta-libを使えば、簡単に計算できます。

3. バックテストシステムの構築

「このロジックで過去1年間トレードしたら、どれくらい利益が出たのか?」

これを検証するバックテストシステムを作ります。

4. 機械学習モデルの実装

最終的には、機械学習で相場を予測するモデルを作りたい。

  • LSTM(時系列予測)
  • ランダムフォレスト
  • XGBoost

など、いろいろ試してみる予定です。

5. リアルタイム取引への応用

バックテストで良い結果が出たら、リアルタイムの自動取引も視野に入れています。

もちろん、少額からスタートして、リスク管理はしっかりと。

まとめ:自動化は最高

Selenium と uv を使って、OANDAからのTickデータ自動ダウンロードシステムを作りました。

自動化して良かったこと:

  • 時間の節約(年間2時間以上)
  • 精神的な負担がゼロに
  • データが確実に溜まる
  • 本質的な作業(分析)に集中できる

技術的なポイント:

  • Seleniumのヘッドレスモード
  • uvの高速なパッケージ管理
  • ログでの動作監視
  • cronでの自動実行

学んだこと:

  • 単純作業は絶対に自動化すべき
  • デバッグモードは必須
  • ログは詳細に残す
  • エラーハンドリングは丁寧に

「めんどくさい作業」は、エンジニアにとって自動化のチャンスです。

今回の自動化で、FXデータ分析の環境が整いました。ここから、本格的にデータと向き合っていきます。

次回は、溜まったデータを使った分析結果を共有する予定です。お楽しみに!


追記: このバッチのコードは、そのうちGitHubで公開するかもしれません。需要があれば、ぜひコメントで教えてください!