蓄積したデータをどう活かすか

前回までで、JPXの信用残データを毎日自動収集し、pickleとCSVに履歴を蓄積する仕組みが完成しました。次の課題は「このデータをどう分析し、株式売買の判断に活かすか」です。

信用残データは需給を読むための強力な材料ですが、数百銘柄分の生データをただ眺めるだけでは何も見えてきません。そこで、データから自動的に「注目すべき銘柄」を抽出するロジックを組み込んだHTMLダッシュボードを作ることにしました。

分析視点の整理:5つのアプローチ

実装に入る前に、どういった分析視点が有効かを整理しました。最終的に以下の5つの軸でシグナルを設計しています。

分析視点内容
需給シグナル系取組比率の水準、売残・買残の急増急減を直接的に見る
変化率・モメンタム系前日比の連続方向(3日連続増など)、5日・20日の累積変化
市場・セクター横断系プライム・スタンダード・グロース別の需給傾向
アノマリー・統計系取組比率の分布における極端値の検出
複合スコアリング系複数指標を組み合わせて「踏み上げ候補」「需給悪化警戒」などのスコアを算出

このうち、最初のダッシュボードに実装したのは「需給シグナル系」「変化率・モメンタム系」「複合スコアリング系」の3つです。これらをJavaScript(ブラウザ側)で自動計算するロジックを組みました。

踏み上げ候補スコアの実装

「踏み上げ候補」とは、空売りをしている人が将来買い戻さざるを得なくなり、株価が急騰するリスクが高い銘柄のことです。以下の4条件を満たすほどスコアが高くなるよう設計しました。

踏み上げ候補スコアの条件(各+1pt、最大5pt)

  • 売残高が全体の上位20%に入っている
  • 取組比率(買残÷売残)が1.0以下
  • 売残が前日比でマイナス(空売りの買い戻し・撤退が始まっている)
  • 一般信用の売残比率が50%を超えている

JavaScriptでの実装はこのようになっています。

// 踏み上げ候補スコア計算
let fumiage = 0;
if (uri > 0) fumiage++;
if (tori > 0 && tori <= 1.0) {
  fumiage++;
  signals.push({type:'f', label:'取組比率低'});
}
if (uChg < 0) {
  fumiage++;
  signals.push({type:'f', label:'売残減少中'});
}
if (uri > 0 && ippanUri / uri > 0.5) {
  fumiage++;
  signals.push({type:'f', label:'一般信用売高'});
}

// 売残上位20%判定(全銘柄から相対的に算出)
const uriVals = allRows
  .filter(r => r._uri > 0)
  .map(r => r._uri)
  .sort((a, b) => b - a);
const p20 = uriVals[Math.floor(uriVals.length * 0.2)] || 0;

allRows.forEach(r => {
  if (r._uri >= p20 && r._uri > 0) {
    r.fumiage_score++;
    r.signals.push({type:'f', label:'売残上位20%'});
  }
});

「売残上位20%」の判定は、その銘柄単体の値だけでは決められないため、全銘柄のデータが揃った後に一括で相対的なしきい値(パーセンタイル)を計算する必要があります。このため、個別銘柄のスコア計算とは別のループで後付けする形にしています。

需給悪化警戒スコアの実装

逆に「需給悪化警戒」は、買い方が過熱し将来的に売り圧力が強まりそうな銘柄を検出するためのスコアです。

需給悪化警戒スコアの条件(各+1pt、最大4pt)

  • 買残が前日比でプラス
  • 取組比率が10倍を超えている(過熱)
  • 買残の上場比率(流通株式数に対する比率)が10%を超えている
  • 買残の上場比率が20%を超えている(追加でさらに+1pt)
let akusei = 0;
if (kChg > 0) akusei++;
if (tori > 10) {
  akusei++;
  signals.push({type:'a', label:'取組比率過熱'});
}
if (kJojo > 10) {
  akusei++;
  signals.push({type:'a', label:'上場比率高'});
}
if (kJojo > 20) {
  akusei++;
  signals.push({type:'a', label:'上場比率超高'});
}

取組比率の高さは「買い方が圧倒的に優勢」であることを示しますが、買残の絶対量が流通株式数に対してどれくらい重いか(上場比率)も併せて見ないと、本当に需給が悪化しているのか判断しづらいため、この2軸を組み合わせています。

買残3日連続増トレンドと売残急減シグナル

単日の前日比だけではノイズが多いため、複数日の連続性を見るロジックも組み込みました。

買残3日連続増加トレンド

各銘柄の履歴データ(蓄積されたCSVの全レコード)を日付順に並べ、直近3件の前日比がすべてプラスかどうかを判定します。

let trendFlag = false;
if (rows.length >= 3) {
  trendFlag = rows.slice(-3).every((r, i) =>
    i === 0 || pn(r["合計_買残高_前日比"]) > 0
  );
  if (trendFlag) {
    const prevTori = rows.length >= 2
      ? pn(rows[rows.length - 2]["取組比率"])
      : 0;
    signals.push({
      type: 't',
      label: tori > prevTori ? '買残3日増+取組↑' : '買残3日連続増'
    });
  }
}

slice(-3) で直近3件を取得し、every() で全件チェックする書き方です。最初の1件目(i === 0)は前日比較ができないため、判定をスキップしています。取組比率が同時に上昇していれば、より強いトレンド継続シグナルとしてラベルを変えています。

売残急減シグナル(踏み上げ発生中の可能性)

売残が前日比で大きく減少した場合は、踏み上げが実際に発生している可能性を示すシグナルとして扱います。減少率を計算し、10%以上の急減を検出します。

const uChgPct = uri > 0 ? uChg / (uri - uChg) * 100 : 0;
let alertFlag = false;
if (uChg < 0 && Math.abs(uChgPct) >= 10) {
  alertFlag = true;
  signals.push({type:'p', label:'売残急減'});
}

また、5営業日前のデータと比較した変化率も別途計算し、モーダル詳細画面で参照できるようにしています。

let uri5d = null, kai5d = null;
if (rows.length >= 5) {
  const r5 = rows[rows.length - 5];
  const u5 = pn(r5["合計_売残高"]);
  const k5 = pn(r5["合計_買残高"]);
  if (u5 > 0) uri5d = (uri - u5) / u5 * 100;
  if (k5 > 0) kai5d = (kai - k5) / k5 * 100;
}

HTMLダッシュボードの構成

計算したシグナル・スコアは、フィルタ・ソート可能なHTMLダッシュボードに表示します。全体構成は以下のとおりです。

ダッシュボードの主な機能

  • KPIカード:総銘柄数・踏み上げ候補数・需給悪化警戒数・買残増加トレンド数・売残急減数をカード形式で表示。クリックでそのまま絞り込みフィルタになる
  • フィルタチップ:銘柄コード・銘柄名検索、シグナル種別の絞り込み、市場(プライム/スタンダード/グロース)選択
  • ソート:踏み上げスコア・需給悪化スコア・売残高・買残高・取組比率などで並び替え
  • テーブルヘッダクリックソート:各列ヘッダをクリックして直接ソート、再クリックで昇順/降順切り替え
  • ページャー:25/50/100/200件の表示切り替え、ページ送りでもスクロール位置を保持

データの読み込みは、収集スクリプトが出力した history.csv をブラウザ側でfetchし、簡易CSVパーサーでパースしてからシグナル計算ロジックに渡す構成です。ローカルファイル(file://)ではfetchがブラウザのセキュリティ制限でブロックされるため、簡易Webサーバー(python -m http.server)経由でアクセスする運用にしています。

async function init() {
  try {
    const r = await fetch(DATA_PATH + "history.csv?t=" + Date.now());
    if (r.ok) {
      processData(parseCSV(await r.text()));
      return;
    }
  } catch(e) {}
  loadDemoData(); // CSVがない場合はデモデータで動作確認
}

HTMLファイルとCSVファイルを同じフォルダに置き、そのフォルダで簡易サーバーを起動するだけで動作する、ポータブルな構成にしています。次回は、銘柄をクリックした際に表示するモーダルウィンドウの実装と、TradingViewの日足チャートをモーダル内に埋め込む方法を解説します。

FAQ

取組比率とは何ですか?

取組比率は買残高÷売残高で計算される値で、貸借倍率とも呼ばれます。1.0未満の場合は売り方(空売り)が買い方より多い状態を示し、将来的に買い戻しによる踏み上げが発生するリスクが高いとされています。

踏み上げ候補スコアはどのように計算していますか?

売残高が全体の上位20%に入っているか、取組比率が1.0以下か、売残が前日比で減少しているか、一般信用の売残比率が50%を超えているか、の4条件をそれぞれ1ポイントとして加算し、最大5点でスコアリングしています。

なぜCSVをJavaScriptでパースしているのですか?

ローカルファイル(file://)ではブラウザのセキュリティ制限によりfetchが使えないケースがあります。簡易Webサーバー経由でCSVをfetchし、ブラウザ側のJavaScriptでパース・シグナル計算まで完結させることで、サーバーサイドの処理を最小限にしています。