環境設定に数時間費やした現実逃避で
昔の手書きで書き込んでいた日経平均先物のカギ足チャートが出てきました。
懐かしいなと思いつつも今なら自動化できるんじゃないかと思い、試してみました。
カギ足チャートってなに?
カギ足チャートとは、値動きの転換点だけを描くチャートです。
時間の経過ではなく値動き幅を基準にして、上昇と下落を折れ線で描いていきます。
投資家心理を排除するために編み出されたシステムトレード用の手法ですね。
ざっくり言うと:
・一定幅(例:100円)上がったら上向きの線を延ばす
・一定幅下がったら下向きに転換する
・「ノイズの少ないトレンド把握」ができる
つまり、「上がった・下がった」を感覚的に追えるチャートです。
昔は紙にペンで書いていたのですが、
Excelなら自動で転換判定して線を引けるはず。
どうやってExcelで自動化したか
方針
* データのソースはこちらから
-
日経平均先物のデータ(始値・高値・安値・終値)を表にする
-
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
出力結果イメージ
苦労した点と工夫した点
苦労した点:
- データの小数点誤差で転換判定がズレることがありました。
→ Round()で値を丸めて安定化させました。
工夫した点:
- 転換幅(100円)はユーザ設定部分にして柔軟に変更可能に。
- グラフは日付をX軸にして“日をまたぐと一マス右へ”という昔の手書き感も再現しました。
完成した折れ線グラフを見てみると、
当時の自分が見ていたをそのまま感じられて感動しました。

