島根県安来市のフリーランスエンジニア_プログラマー画像1
リアルタイム株価アラートシステムの作り方|実装ガイド完全版 – Eatransform

リアルタイム株価アラートシステムの作り方|実装ガイド完全版

🚧 デモシステム

📊 リアルタイム株価アラートシステム

設定した条件で株価を24時間監視、即座に通知

🚧 これはデモシステムです

本格的な株価アラートシステムの実装ガイド

リアルタイム監視と自動通知を実現する完全ガイド

1

株価データソースの選定

リアルタイム株価取得のためのAPI選び

  • Alpha Vantage: 無料枠あり、1分足から日足まで対応。リアルタイムデータは1分ごとに更新
  • Yahoo Finance API (yfinance): Pythonライブラリで簡単に利用可能、無料だが非公式
  • Polygon.io: 月$199〜、ミリ秒単位のリアルタイムデータ、米国株特化
  • 楽天証券 MarketSpeed API: 日本株に強い、口座開設が必要
  • Finnhub: 無料枠60リクエスト/分、ニュースやSNS感情分析も取得可能
  • Kabu+ API: auカブコム証券のAPI、日本株のリアルタイム情報

💡 推奨: 個人開発ならAlpha Vantage無料枠でスタート(1日500リクエスト)。本格運用なら楽天証券やauカブコム証券のAPIで日本株に特化するのが現実的です。

2

システムアーキテクチャ設計

24時間稼働する監視システム

  • フロントエンド: React + Next.js でアラート設定UIを構築
  • バックエンド: Node.js + Express または Python + FastAPI
  • データベース: PostgreSQL でユーザー・アラート設定を保存
  • 監視システム: cron / 定期ジョブで1分〜5分ごとに株価をチェック
  • キャッシュ: Redis で株価データをキャッシュし、API呼び出しを削減
  • 通知サービス: SendGrid(メール)、LINE Messaging API、FCM(プッシュ通知)
  • WebSocket: リアルタイムで株価更新をクライアントに配信
🛠️ 推奨技術スタック
React + Next.js Node.js / Python PostgreSQL Redis Alpha Vantage API SendGrid LINE Messaging API WebSocket
3

株価取得システムの実装

Alpha Vantage APIで株価を取得

  • リアルタイムクォート: TIME_SERIES_INTRADAYで1分足データ取得
  • 日次データ: TIME_SERIES_DAILYで過去の終値・始値など
  • レート制限: 無料枠は1分5リクエスト、1日500リクエスト
  • キャッシング戦略: 同じ銘柄は1分間キャッシュしてAPI呼び出しを節約
📡 Alpha Vantage API実装例(Node.js)
const axios = require('axios');
const redis = require('redis');
const client = redis.createClient();

const API_KEY = process.env.ALPHA_VANTAGE_KEY;

async function getStockPrice(symbol) {
  // Redisキャッシュをチェック
  const cached = await client.get(`stock:${symbol}`);
  if (cached) {
    return JSON.parse(cached);
  }

  // APIから取得
  const url = `https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=${symbol}&apikey=${API_KEY}`;
  const response = await axios.get(url);
  
  const data = response.data['Global Quote'];
  const stockData = {
    symbol: data['01. symbol'],
    price: parseFloat(data['05. price']),
    change: parseFloat(data['09. change']),
    changePercent: parseFloat(data['10. change percent'].replace('%', '')),
    volume: parseInt(data['06. volume']),
    timestamp: new Date()
  };

  // 1分間キャッシュ
  await client.setEx(`stock:${symbol}`, 60, JSON.stringify(stockData));
  
  return stockData;
}

// 使用例
const toyotaPrice = await getStockPrice('7203.T'); // 東京証券取引所
console.log(`トヨタ株価: ${toyotaPrice.price}円`);

⚠️ 注意: Alpha Vantageは米国株がメイン。日本株は銘柄コードに「.T」を付けて「7203.T」のように指定しますが、データが取得できない場合があります。日本株専用にはYahoo Finance APIやカブドットコム証券APIを検討してください。

4

アラート条件判定ロジック

ユーザー設定に基づく条件チェック

  • 価格ベース: 「3,500円以上」「3,000円以下」などの閾値判定
  • 変動率ベース: 「前日比+5%以上」「1時間で-3%以上」
  • 出来高ベース: 「平均出来高の200%超え」で急騰・急落を検知
  • テクニカル指標: 移動平均線のゴールデンクロス・デッドクロス
  • 複合条件: AND/OR条件で複雑なアラート設定
🎯 アラート判定ロジック
async function checkAlerts() {
  // データベースから全アクティブアラートを取得
  const alerts = await db.query('SELECT * FROM alerts WHERE active = true');

  for (const alert of alerts) {
    const stockData = await getStockPrice(alert.symbol);
    let shouldTrigger = false;
    let message = '';

    // 上限価格チェック
    if (alert.upper_limit && stockData.price >= alert.upper_limit) {
      shouldTrigger = true;
      message = `${alert.symbol}が${alert.upper_limit}円を上回りました!現在価格: ${stockData.price}円`;
    }

    // 下限価格チェック
    if (alert.lower_limit && stockData.price <= alert.lower_limit) {
      shouldTrigger = true;
      message = `${alert.symbol}が${alert.lower_limit}円を下回りました!現在価格: ${stockData.price}円`;
    }

    // 変動率チェック
    if (alert.change_percent && Math.abs(stockData.changePercent) >= alert.change_percent) {
      shouldTrigger = true;
      message = `${alert.symbol}が${stockData.changePercent}%変動しました!`;
    }

    // アラート発動
    if (shouldTrigger) {
      await sendNotification(alert.user_id, message, alert.notification_methods);
      await db.query('UPDATE alerts SET last_triggered = NOW() WHERE id = ?', [alert.id]);
    }
  }
}

// 1分ごとに実行
setInterval(checkAlerts, 60000);
5

メール通知の実装

SendGridで即座にメール送信

  • SendGrid無料枠: 月100通まで無料、それ以降は従量課金
  • HTMLメール: 株価チャート画像を埋め込み、視覚的に分かりやすく
  • 配信速度: 通常3-5秒以内に届く
  • バッチ送信: 複数ユーザーに一括送信でコスト削減
📧 SendGrid実装例
const sgMail = require('@sendgrid/mail');
sgMail.setApiKey(process.env.SENDGRID_API_KEY);

async function sendEmailAlert(userEmail, stockSymbol, price, message) {
  const msg = {
    to: userEmail,
    from: 'alerts@stockalert.com',
    subject: `🔔 ${stockSymbol} 株価アラート発動!`,
    text: message,
    html: `
      <div style="font-family: sans-serif; padding: 20px;">
        <h2 style="color: #667eea;">🔔 株価アラートが発動しました!</h2>
        <div style="background: #f3f4f6; padding: 20px; border-radius: 10px; margin: 20px 0;">
          <h3>${stockSymbol}</h3>
          <p style="font-size: 24px; font-weight: bold; color: #1f2937;">${price}円</p>
          <p>${message}</p>
        </div>
        <a href="https://yourapp.com/alerts" style="background: #667eea; color: white; padding: 12px 24px; text-decoration: none; border-radius: 8px; display: inline-block;">
          アラート管理画面を開く
        </a>
      </div>
    `
  };

  await sgMail.send(msg);
  console.log(`メール送信完了: ${userEmail}`);
}
6

LINE通知の実装

LINE Messaging APIで即座に通知

  • LINE Notify: 最も簡単、個人向けトークンで通知送信
  • LINE Messaging API: 本格的なBot、双方向やりとり可能
  • リッチメッセージ: 画像やボタン付きメッセージで視認性向上
  • 無料枠: 月1,000通まで無料、それ以降は従量課金
💬 LINE Notify実装例
const axios = require('axios');

async function sendLineNotify(token, message) {
  await axios.post(
    'https://notify-api.line.me/api/notify',
    `message=${encodeURIComponent(message)}`,
    {
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Authorization': `Bearer ${token}`
      }
    }
  );
}

// LINE Messaging API版
const line = require('@line/bot-sdk');

const client = new line.Client({
  channelAccessToken: process.env.LINE_CHANNEL_ACCESS_TOKEN
});

async function sendLineMessage(userId, stockSymbol, price) {
  const message = {
    type: 'flex',
    altText: `${stockSymbol} 株価アラート`,
    contents: {
      type: 'bubble',
      hero: {
        type: 'box',
        layout: 'vertical',
        contents: [
          {
            type: 'text',
            text: '🔔 株価アラート',
            weight: 'bold',
            size: 'xl',
            color: '#ffffff'
          }
        ],
        backgroundColor: '#667eea',
        paddingAll: '20px'
      },
      body: {
        type: 'box',
        layout: 'vertical',
        contents: [
          {
            type: 'text',
            text: stockSymbol,
            weight: 'bold',
            size: 'lg'
          },
          {
            type: 'text',
            text: `${price}円`,
            size: 'xxl',
            weight: 'bold',
            color: '#667eea'
          }
        ]
      }
    }
  };

  await client.pushMessage(userId, message);
}

💡 ユーザー体験: LINE通知は開封率が非常に高く(80%以上)、即座に確認されます。メールよりも緊急性の高いアラートに最適です。

7

プッシュ通知の実装

Firebase Cloud Messaging (FCM)

  • 対応プラットフォーム: iOS、Android、Webブラウザ全対応
  • 完全無料: 制限なしで無料利用可能
  • 到達率: 90%以上の高い到達率
  • カスタマイズ: アイコン、音、振動パターンを設定可能
  • バックグラウンド通知: アプリが起動していなくても通知が届く
📱 FCMプッシュ通知実装
const admin = require('firebase-admin');

admin.initializeApp({
  credential: admin.credential.applicationDefault()
});

async function sendPushNotification(deviceToken, stockSymbol, price, message) {
  const payload = {
    notification: {
      title: `🔔 ${stockSymbol} 株価アラート`,
      body: `現在価格: ${price}円 - ${message}`,
      icon: '/icon-192x192.png',
      badge: '/badge-72x72.png',
      sound: 'default',
      click_action: 'https://yourapp.com/alerts'
    },
    data: {
      stockSymbol: stockSymbol,
      price: price.toString(),
      timestamp: new Date().toISOString()
    }
  };

  const response = await admin.messaging().send({
    token: deviceToken,
    notification: payload.notification,
    data: payload.data,
    android: {
      priority: 'high',
      notification: {
        sound: 'default',
        channelId: 'stock-alerts'
      }
    },
    apns: {
      payload: {
        aps: {
          sound: 'default',
          badge: 1
        }
      }
    }
  });

  console.log('プッシュ通知送信完了:', response);
}

⚠️ 重要: プッシュ通知を使用する場合、ユーザーから通知許可を取得する必要があります。また、iOSではAPNs証明書の設定が必要です。

8

データベース設計

ユーザーとアラート情報の管理

  • users テーブル: ユーザー情報、通知設定
  • alerts テーブル: アラート条件、監視銘柄
  • alert_history テーブル: 過去の発動履歴
  • stocks テーブル: 銘柄マスターデータ
  • stock_prices テーブル: 過去の株価データ(分析用)
🗄️ PostgreSQL スキーマ設計
-- ユーザーテーブル
CREATE TABLE users (
  id SERIAL PRIMARY KEY,
  email VARCHAR(255) UNIQUE NOT NULL,
  line_user_id VARCHAR(255),
  fcm_token TEXT,
  notification_email BOOLEAN DEFAULT true,
  notification_line BOOLEAN DEFAULT false,
  notification_push BOOLEAN DEFAULT false,
  created_at TIMESTAMP DEFAULT NOW()
);

-- アラートテーブル
CREATE TABLE alerts (
  id SERIAL PRIMARY KEY,
  user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
  stock_symbol VARCHAR(20) NOT NULL,
  stock_name VARCHAR(100),
  upper_limit DECIMAL(10,2),
  lower_limit DECIMAL(10,2),
  change_percent DECIMAL(5,2),
  volume_multiplier DECIMAL(4,2),
  active BOOLEAN DEFAULT true,
  last_triggered TIMESTAMP,
  created_at TIMESTAMP DEFAULT NOW(),
  INDEX idx_user_active (user_id, active),
  INDEX idx_stock_active (stock_symbol, active)
);

-- 発動履歴テーブル
CREATE TABLE alert_history (
  id SERIAL PRIMARY KEY,
  alert_id INTEGER REFERENCES alerts(id) ON DELETE CASCADE,
  trigger_price DECIMAL(10,2),
  trigger_type VARCHAR(50),
  message TEXT,
  triggered_at TIMESTAMP DEFAULT NOW(),
  INDEX idx_alert_time (alert_id, triggered_at)
);

-- 銘柄マスターテーブル
CREATE TABLE stocks (
  symbol VARCHAR(20) PRIMARY KEY,
  name VARCHAR(100) NOT NULL,
  market VARCHAR(50),
  sector VARCHAR(100),
  updated_at TIMESTAMP DEFAULT NOW()
);
9

フロントエンド実装

直感的なアラート設定UI

  • 銘柄検索: 銘柄コードや会社名で検索、サジェスト機能
  • リアルタイム価格表示: WebSocketで株価を自動更新
  • ビジュアライゼーション: Chart.jsでミニチャート表示
  • アラート管理: 一覧表示、編集、削除、一時停止
  • 通知履歴: 過去の発動履歴を時系列表示
⚛️ React実装例
import { useState, useEffect } from 'react';
import io from 'socket.io-client';

function StockAlertDashboard() {
  const [alerts, setAlerts] = useState([]);
  const [stockPrices, setStockPrices] = useState({});
  
  useEffect(() => {
    // WebSocketで株価をリアルタイム受信
    const socket = io('ws://localhost:3000');
    
    socket.on('price-update', (data) => {
      setStockPrices(prev => ({
        ...prev,
        [data.symbol]: data
      }));
    });
    
    // アラート一覧を取得
    fetchAlerts();
    
    return () => socket.disconnect();
  }, []);
  
  async function fetchAlerts() {
    const res = await fetch('/api/alerts');
    const data = await res.json();
    setAlerts(data);
  }
  
  async function createAlert(alertData) {
    await fetch('/api/alerts', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(alertData)
    });
    fetchAlerts();
  }
  
  return (
    <div className="dashboard">
      <h1>株価アラート管理</h1>
      
      {/* アラート設定フォーム */}
      <AlertForm onSubmit={createAlert} />
      
      {/* アクティブなアラート一覧 */}
      <div className="alert-list">
        {alerts.map(alert => (
          <AlertCard 
            key={alert.id} 
            alert={alert}
            currentPrice={stockPrices[alert.stock_symbol]?.price}
          />
        ))}
      </div>
    </div>
  );
}
10

スケーラビリティと最適化

ユーザー増加に耐えるシステム設計

  • バッチ処理: 同じ銘柄のアラートをまとめて1回のAPI呼び出しで処理
  • 優先度キュー: 発動頻度の高いアラートを優先的にチェック
  • 分散処理: 複数サーバーで銘柄を分散監視
  • 負荷分散: AWS ELB / Nginx でトラフィックを分散
  • データベース最適化: インデックス追加、読み取りレプリカ
  • 通知キュー: RabbitMQ / AWS SQS で通知を非同期処理
⚡ バッチ処理の最適化
async function batchCheckAlerts() {
  // アクティブなアラートをすべて取得
  const alerts = await db.query(`
    SELECT DISTINCT stock_symbol 
    FROM alerts 
    WHERE active = true
  `);
  
  // 銘柄ごとにグループ化
  const symbolGroups = {};
  for (const alert of alerts) {
    if (!symbolGroups[alert.stock_symbol]) {
      symbolGroups[alert.stock_symbol] = [];
    }
    symbolGroups[alert.stock_symbol].push(alert);
  }
  
  // 並列で株価取得(最大10銘柄ずつ)
  const symbols = Object.keys(symbolGroups);
  const chunks = chunkArray(symbols, 10);
  
  for (const chunk of chunks) {
    await Promise.all(
      chunk.map(async (symbol) => {
        const price = await getStockPrice(symbol);
        
        // その銘柄の全アラートをチェック
        for (const alert of symbolGroups[symbol]) {
          await checkAndTriggerAlert(alert, price);
        }
      })
    );
    
    // APIレート制限対策で1秒待機
    await new Promise(resolve => setTimeout(resolve, 1000));
  }
}

function chunkArray(array, size) {
  const chunks = [];
  for (let i = 0; i < array.length; i += size) {
    chunks.push(array.slice(i, i + size));
  }
  return chunks;
}

最適化効果: この方法なら、1,000人のユーザーが100銘柄を監視していても、重複を除いて100回のAPI呼び出しで済みます。

11

コスト試算とマネタイズ

持続可能なビジネスモデル

  • Alpha Vantage: 無料枠で月500リクエスト、有料は月$49.99〜
  • SendGrid: 月100通まで無料、追加は1,000通あたり$14.95
  • LINE Messaging API: 月1,000通まで無料、追加は1,000通あたり¥350
  • Firebase FCM: 完全無料
  • サーバーコスト: AWS EC2 t3.micro(月$10)+ RDS(月$15)
  • 総コスト: 月約$50-100で運用可能

💡 価格設定例:

• 無料プラン: 3銘柄、5アラートまで
• ベーシック(月980円): 10銘柄、無制限アラート
• プロ(月2,980円): 無制限銘柄、テクニカル分析、優先サポート
• エンタープライズ(要相談): API提供、専用サーバー

収益シミュレーション: 月間500ユーザーのうち20%が有料プラン(平均1,500円)に転換すれば、月商15万円。1,000ユーザーで月商30万円を達成できます。

12

今日から始めるMVP

3日間で動くプロトタイプを作る

  • Day 1: Next.jsでUI構築、Alpha Vantage APIで株価取得を実装
  • Day 2: PostgreSQLでデータベース構築、アラート判定ロジック実装
  • Day 3: SendGridでメール通知実装、デプロイ(Vercel + Railway)
🚀 最小構成のコード(Next.js API Route)
// pages/api/check-alerts.js
import { getStockPrice } from '@/lib/alpha-vantage';
import { sendEmail } from '@/lib/sendgrid';
import db from '@/lib/database';

export default async function handler(req, res) {
  // アクティブなアラートを取得
  const alerts = await db.query(`
    SELECT a.*, u.email 
    FROM alerts a
    JOIN users u ON a.user_id = u.id
    WHERE a.active = true
  `);
  
  let triggeredCount = 0;
  
  for (const alert of alerts) {
    const stock = await getStockPrice(alert.stock_symbol);
    
    // 上限チェック
    if (alert.upper_limit && stock.price >= alert.upper_limit) {
      await sendEmail(
        alert.email,
        `${alert.stock_symbol} が ${alert.upper_limit}円を突破!`,
        `現在価格: ${stock.price}円`
      );
      triggeredCount++;
    }
    
    // 下限チェック
    if (alert.lower_limit && stock.price <= alert.lower_limit) {
      await sendEmail(
        alert.email,
        `${alert.stock_symbol} が ${alert.lower_limit}円を下回った!`,
        `現在価格: ${stock.price}円`
      );
      triggeredCount++;
    }
  }
  
  res.json({ success: true, triggered: triggeredCount });
}

// Vercel Cronで1分ごとに実行
// vercel.json に設定:
// {
//   "crons": [{
//     "path": "/api/check-alerts",
//     "schedule": "* * * * *"
//   }]
// }

⚠️ 最初の一歩: 完璧を目指さず、まず「1銘柄、メール通知のみ」の最小機能を完成させましょう。ユーザーフィードバックを得てから機能を追加する方が成功確率が高まります。

ローンチのヒント: Product Hunt、Reddit(r/investing、r/stocks)、Twitter(#投資 #株式)で公開すれば、初日から数百人のユーザーを獲得できる可能性があります。

MTF Market Pulse HUD – 6時間軸対応MT4インジケータ無料配布

Excel比較ツール無料ダウンロード | Excel Comparator