0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

エクセルVBAで日経平均のカギ足チャートを作る

Last updated at Posted at 2025-10-26

環境設定に数時間費やした現実逃避で
昔の手書きで書き込んでいた日経平均先物のカギ足チャートが出てきました。

懐かしいなと思いつつも今なら自動化できるんじゃないかと思い、試してみました。

カギ足チャートってなに?

カギ足チャートとは、値動きの転換点だけを描くチャートです。
時間の経過ではなく値動き幅を基準にして、上昇と下落を折れ線で描いていきます。
投資家心理を排除するために編み出されたシステムトレード用の手法ですね。

ざっくり言うと:

・一定幅(例:100円)上がったら上向きの線を延ばす

・一定幅下がったら下向きに転換する

・「ノイズの少ないトレンド把握」ができる

つまり、「上がった・下がった」を感覚的に追えるチャートです。
昔は紙にペンで書いていたのですが、
Excelなら自動で転換判定して線を引けるはず。

どうやってExcelで自動化したか

方針
* データのソースはこちらから

  • 日経平均先物のデータ(始値・高値・安値・終値)を表にする

  • VBAで「一定幅以上の上昇/下落」を検出し、折れ線グラフとして描画
    image.png

  • Alt + F11 - VBAエディタ(Visual Basic Editor)を開き、コードを入力する。(下記は実際に動いたコード)

.vba
Option Explicit

'==================== ユーザー設定 ====================
Const STEP_YEN As Double = 100 ' 1ボックスの値幅(100円)
'=====================================================

Public Sub BuildKagiLikeRectLine()
    Dim wsIn As Worksheet, wsOut As Worksheet
    Dim lastRow As Long, i As Long
    
    ' --- 入力チェック ---
    On Error Resume Next
    Set wsIn = ThisWorkbook.Worksheets("PRICE")
    On Error GoTo 0
    If wsIn Is Nothing Then
        MsgBox "PRICE シートがありません。A:E に 日付/始値/高値/安値/終値 を置いてください。", vbExclamation
        Exit Sub
    End If
    
    lastRow = wsIn.Cells(wsIn.Rows.Count, "A").End(xlUp).Row
    If lastRow < 2 Then
        MsgBox "PRICE シートにデータがありません。", vbExclamation
        Exit Sub
    End If
    
    ' --- 出力シート(作り直し) ---
    On Error Resume Next
    Application.DisplayAlerts = False
    ThisWorkbook.Worksheets("CHART").Delete
    Application.DisplayAlerts = True
    On Error GoTo 0
    Set wsOut = ThisWorkbook.Worksheets.Add
    wsOut.Name = "CHART"
    
    ' --- 入力配列 ---
    Dim dts() As Variant, opn() As Variant, hi() As Variant, lo() As Variant, cls() As Variant
    dts = wsIn.Range("A2:A" & lastRow).Value
    opn = wsIn.Range("B2:B" & lastRow).Value
    hi  = wsIn.Range("C2:C" & lastRow).Value
    lo  = wsIn.Range("D2:D" & lastRow).Value
    cls = wsIn.Range("E2:E" & lastRow).Value
    
    Dim n As Long: n = UBound(dts, 1)
    
    ' --- 出力テーブル(プロット点を順番に書いていく) ---
    ' A列 = X(日付) , B列 = Y(価格)
    wsOut.Range("A1:B1").Value = Array("X(日付)", "Y(価格)")
    
    Dim rowOut As Long: rowOut = 2
    
    ' 初期位置:1日目の終値を100円グリッドに丸めて開始
    Dim yPrev As Double
    yPrev = RoundToStep(ToNumber(cls(1, 1)), STEP_YEN)
    
    Dim x As Variant ' ← 日付(文字列/Date 両対応)
    x = ToDate(dts(1, 1))
    
    ' 1点目(初日)
    wsOut.Cells(rowOut, 1).Value = x
    wsOut.Cells(rowOut, 2).Value = yPrev
    rowOut = rowOut + 1
    
    ' --- 各営業日で「横→縦ステップ」 ---
    Dim tgt As Double
    Dim seq(1 To 4) As Double
    Dim j As Long
    
    For i = 2 To n
        x = ToDate(dts(i, 1))
        
        ' --- 日をまたぐ水平(横棒) ---
        wsOut.Cells(rowOut, 1).Value = x
        wsOut.Cells(rowOut, 2).Value = yPrev
        rowOut = rowOut + 1
        
        ' --- 当日内:Open→High→Low→Close を縦ステップ ---
        seq(1) = ToNumber(opn(i, 1))
        seq(2) = ToNumber(hi(i, 1))
        seq(3) = ToNumber(lo(i, 1))
        seq(4) = ToNumber(cls(i, 1))
        
        For j = 1 To 4
            tgt = RoundToStep(seq(j), STEP_YEN)
            rowOut = WriteVerticalSteps(wsOut, rowOut, x, yPrev, tgt)
            yPrev = tgt
        Next j
    Next i
    
    ' --- 体裁 ---
    wsOut.Columns("A:B").AutoFit
    wsOut.Range("A2:A" & rowOut - 1).NumberFormatLocal = "yyyy/m/d"
    wsOut.Range("B2:B" & rowOut - 1).NumberFormatLocal = "#,##0"
    
    ' --- グラフ(XY散布:直線) ---
    Dim co As ChartObject, ch As Chart
    Set co = wsOut.ChartObjects.Add(Left:=260, Top:=10, Width:=900, Height:=440)
    Set ch = co.Chart
    ch.ChartType = xlXYScatterLines ' 直線
    ch.SetSourceData wsOut.Range("A1:B" & rowOut - 1)
    ch.HasTitle = True
    ch.ChartTitle.Text = "カギ足(矩形波)折れ線:横=日付、縦=価格(100円刻み)"
    
    ' X軸(日付)
    With ch.Axes(xlCategory)
        .HasMajorGridlines = True
        .TickLabels.NumberFormatLocal = "m/d"
    End With
    ' Y軸(価格)
    With ch.Axes(xlValue)
        .TickLabels.NumberFormatLocal = "#,##0"
        .HasMajorGridlines = True
    End With
    
    MsgBox "短形波(1日ごと横→縦ステップ)の折れ線を CHART シートに作成しました。", vbInformation
End Sub

'=== 数値化:カンマ除去 → 数値 ===
Private Function ToNumber(ByVal v As Variant) As Double
    If IsError(v) Or IsEmpty(v) Then
        ToNumber = 0
        Exit Function
    End If
    Dim s As String
    s = CStr(v)
    s = Replace(s, ",", "") ' 千位カンマ除去
    If Len(s) = 0 Then
        ToNumber = 0
    ElseIf IsNumeric(s) Then
        ToNumber = CDbl(s)
    Else
        ' 数値にならない場合は 0(必要ならエラーにしてもOK)
        ToNumber = 0
    End If
End Function

'=== 日付化:"2025.10.01" → "2025/10/01" にして日付化を試みる ===
Private Function ToDate(ByVal v As Variant) As Variant
    If IsError(v) Or IsEmpty(v) Then
        ToDate = v
        Exit Function
    End If
    Dim s As String
    s = CStr(v)
    If IsDate(v) Then
        ToDate = CDate(v)
    ElseIf InStr(s, ".") > 0 Then
        s = Replace(s, ".", "/")
        If IsDate(s) Then
            ToDate = CDate(s)
        Else
            ToDate = v ' 文字列のまま(XY散布のX値としては日付型でなくても描画可能)
        End If
    Else
        ToDate = v
    End If
End Function

'=== 100円格子への丸め(四捨五入)===
Private Function RoundToStep(ByVal val As Double, ByVal stepYen As Double) As Double
    If val >= 0 Then
        RoundToStep = stepYen * Int((val / stepYen) + 0.5)
    Else
        RoundToStep = stepYen * -Int((-val / stepYen) + 0.5)
    End If
End Function

'=== 縦のステップ(x固定、yを100円刻みで fromY → toY)===
Private Function WriteVerticalSteps(ByVal ws As Worksheet, ByVal rowStart As Long, _
                                    ByVal x As Variant, ByVal fromY As Double, ByVal toY As Double) As Long
    Dim rowOut As Long: rowOut = rowStart
    Dim y As Double, dir As Long
    
    If toY = fromY Then
        ws.Cells(rowOut, 1).Value = x
        ws.Cells(rowOut, 2).Value = fromY
        rowOut = rowOut + 1
        WriteVerticalSteps = rowOut
        Exit Function
    End If
    
    dir = Sgn(toY - fromY)
    y = fromY
    Do While y <> toY
        y = y + dir * STEP_YEN
        ws.Cells(rowOut, 1).Value = x
        ws.Cells(rowOut, 2).Value = y
        rowOut = rowOut + 1
    Loop
    
    WriteVerticalSteps = rowOut
End Function

出力結果イメージ

image.png

苦労した点と工夫した点

苦労した点:

  • データの小数点誤差で転換判定がズレることがありました。
    → Round()で値を丸めて安定化させました。

工夫した点:

  • 転換幅(100円)はユーザ設定部分にして柔軟に変更可能に。
  • グラフは日付をX軸にして“日をまたぐと一マス右へ”という昔の手書き感も再現しました。

完成した折れ線グラフを見てみると、
当時の自分が見ていたをそのまま感じられて感動しました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?