ラベル トレーディング の投稿を表示しています。 すべての投稿を表示
ラベル トレーディング の投稿を表示しています。 すべての投稿を表示

2026-03-12

TA-Lib の Streaming API

2001 年にリリースされた TA-Lib, Technical Analysis Library は、150 以上のテクニカル指標をサポートしていて、長年にわたる検証を経ています。現在の Python 用パッケージは、Cython と Numpy を用いて効率的かつクリーンに TA-Lib をバインドしています。TA-Lib は BSD License (BSD-2-Clause license) の元で配布されているオープンソースのライブラリです。

株価の値動きなどを分析する際に TA-Lib のパッケージを利用していますが、デイトレ用のリアルタイム・システムで利用しようとすると、ちょっと扱いにくいと感じていました。それは、TA-Lib では全てのデータ列に対して計算するからです。そのため、リアルタイムの処理では専用の処理をするクラスを用意して対応しているのですが、計算負荷を少なくするための検討は結構面倒な作業です。

Github の TA-Lib / ta-lib-python プロジェクトサイトにある README をよく読むと、実験段階ながら Streaming API が提供されていることがわかりました。

詳細なベンチマークテストをしていませんが(下に追記しました [2026-03-12])、リアルタイム風に動作するサンプルを作ったので紹介します。

下記の OS 環境で動作確認をしています。

Fedora Linux 43 x86_64
Workstation Edition
Python 3.14.3
numpy 2.4.3
pandas 3.0.1
pyqtgraph 0.14.0
pyside6 6.10.2
ta-lib 0.6.8

TA-Lib の Streaming API とは

従来の API は、過去データ全体に対してインジケーターを計算する設計です。

import numpy as np
import talib as ta

# 過去のデータ全体を一度に処理
prices = np.array([100, 101, 102, 103, 104, 105], dtype=float)
ma = ta.SMA(prices, timeperiod=3)
# 結果:
print(ma)
[ nan  nan 101. 102. 103. 104.]

Streaming API は、直近のデータウィンドウに対してインジケーターを計算します。

import numpy as np
from talib import stream

# 新しいデータポイントが到着するたびに計算
buffer = np.array([100, 101, 102], dtype=float)
ma = stream.SMA(buffer, timeperiod=3)
print(ma)

# 次のデータが到着
buffer = np.array([101, 102, 103], dtype=float)
ma = stream.SMA(buffer, timeperiod=3)
print(ma)
101.0
102.0

Streaming API の主な特徴

  1. 固定長バッファで動作
    • 計算に必要な期間(例:30 期間)のデータのみを保持
    • メモリ効率が良い
  2. 最新値のみを返す
    • 従来の API は配列全体を返すが、Streaming API は単一の値を返す
      • Streaming API は、渡された配列全体に対してインジケーターを計算し、最後の値だけを返す関数です。つまり 1000 個のデータを渡せば 1000 個分の計算をしてしまいます。
      • そのため、プログラム側で固定長バッファを管理する必要があります。
    • リアルタイムモニタリングに最適
  3. 実験的機能 (Experimental)
    • まだ開発中の機能なので、将来的に仕様が変更される可能性がある
    • プロダクション環境では慎重に使用すること

サンプル

ティックデータから単純な移動平均 MA (n=30) を算出して、株価トレンドと一緒にプロットするサンプルです。チャート作成には PyQtGraph を利用しています。

ツールバーにある ▶(再生ボタン)をクリックすると過去のティックデータ(下記サンプル)を読み込み、100 msec 間隔で新しい点を繋げてプロットします。MA を算出できるようになったら緑線で表示されるようになります。

放っておけばデータの最後までプロットしますが、途中で止める場合は、ツールバーにある ⏹(停止ボタン)をクリックします。

sample_data.zip サンプルプログラムが読み込むティックデータ

※ このティックデータは、楽天証券のマーケットスピード2 RSS 経由で自作アプリが収集した 2 秒間隔のティックデータです。

上記のサンプルデータを zip のままで、下記サンプルと同じディレクトリ内に保存してサンプルを実行してください。

import sys
from typing import Optional

import numpy as np
import pandas as pd
import pyqtgraph as pg
from PySide6.QtCore import QTimer
from PySide6.QtWidgets import QApplication, QMainWindow, QStyle, QToolBar, QToolButton
from talib import stream


class SampleChart(pg.PlotWidget):
    def __init__(self, ma_period: int = 30) -> None:
        super().__init__()
        self.ma_period = ma_period

        # リストで保持(append が高速)
        self.data_x: list[float] = []
        self.data_y: list[float] = []
        self.data_ma: list[float] = []

        # streaming APIの状態を保持するためのバッファ
        self.y_buffer = np.array([], dtype=float)

        self.line: pg.PlotDataItem = self.plot([], [], pen=pg.mkPen(width=0.5))
        self.ma: pg.PlotDataItem = self.plot([], [], pen=pg.mkPen((0, 255, 0, 192), width=1))

    def add_point(self, x: float, y: float) -> None:
        """新しいデータポイントを追加"""
        self.data_x.append(x)
        self.data_y.append(y)

        # バッファを更新(直近ma_period個のデータのみ保持)
        self.y_buffer = np.append(self.y_buffer, y)
        if len(self.y_buffer) > self.ma_period:
            self.y_buffer = self.y_buffer[-self.ma_period:]

        # streaming APIで移動平均を計算
        if len(self.y_buffer) >= self.ma_period:
            self.data_ma.append(stream.SMA(self.y_buffer, timeperiod=self.ma_period))

        # グラフを更新
        self.line.setData(self.data_x, self.data_y)  # type: ignore

        # MA期間に達したらMAラインを表示
        if len(self.data_ma) > 0:
            ma_start = self.ma_period - 1
            self.ma.setData(self.data_x[ma_start:], self.data_ma)  # type: ignore


class SampleTaLib(QMainWindow):
    def __init__(self) -> None:
        super().__init__()
        self.file_csv = "sample_data.zip"  # ZIP圧縮されたCSVファイルを読み込む
        self.df: Optional[pd.DataFrame] = None
        self.row: int = 0

        self.setWindowTitle("TA-Lib Streaming API Demo")
        self.resize(800, 600)

        # ツールバーの設定
        toolbar = QToolBar()

        but_play = QToolButton()
        but_play.setIcon(self.style().standardIcon(QStyle.StandardPixmap.SP_MediaPlay))
        but_play.clicked.connect(self.on_play_clicked)
        toolbar.addWidget(but_play)

        but_stop = QToolButton()
        but_stop.setIcon(self.style().standardIcon(QStyle.StandardPixmap.SP_MediaStop))
        but_stop.clicked.connect(self.on_stop_clicked)
        toolbar.addWidget(but_stop)

        self.addToolBar(toolbar)

        # チャートの設定
        self.chart = SampleChart(ma_period=30)
        self.setCentralWidget(self.chart)

        # タイマーの設定
        self.timer = QTimer()
        self.timer.setInterval(100)
        self.timer.timeout.connect(self.set_new_data)

    def on_play_clicked(self) -> None:
        """再生ボタンクリック時の処理"""
        try:
            # データ未読み込みの場合のみ読み込む
            if self.df is None:
                self.df = pd.read_csv(self.file_csv)
                print(f"CSVファイルを読み込みました: {len(self.df)}行")

                # データの検証
                if len(self.df.columns) < 2:
                    print("エラー: CSVファイルには少なくとも2列必要です")
                    return

            if not self.timer.isActive():
                self.timer.start()
                print("タイマーを開始しました。")

        except FileNotFoundError:
            print(f"エラー: ファイル '{self.file_csv}' が見つかりません")
        except Exception as e:
            print(f"エラー: {e}")

    def on_stop_clicked(self) -> None:
        """停止ボタンクリック時の処理"""
        if self.timer.isActive():
            self.timer.stop()
            print("タイマーを停止しました。")

    def set_new_data(self) -> None:
        """新しいデータをチャートに追加"""
        if self.df is None or self.row >= len(self.df):
            self.on_stop_clicked()
            print("データの最後に到達しました。")
            return

        try:
            x, y = self.df.iloc[self.row, 0], self.df.iloc[self.row, 1]
            self.chart.add_point(float(x), float(y))
            self.row += 1
        except Exception as e:
            print(f"データ追加エラー: {e}")
            self.on_stop_clicked()


def main() -> None:
    app = QApplication(sys.argv)
    win = SampleTaLib()
    win.show()
    sys.exit(app.exec())


if __name__ == "__main__":
    main()
CSVファイルを読み込みました: 9691行
タイマーを開始しました。
タイマーを停止しました。
サンプルの実行例

ベンチマーク 追記 [2026-03-12]

Anthropic Claude にベンチマーク用のコードを作ってもらいました。現行のアプリに採用している移動平均を算出するクラスのコア部分を抽出したクラスと、今回の TA-Lib の Streaming API を適用したクラスで比較しました。

import time
from collections import deque
import numpy as np
from talib import stream

# 現在の実装
class MovingAverage:
    def __init__(self, window_size: int):
        self.window_size = window_size
        self.queue = deque()
        self.running_sum = 0.0
        self.ma = 0.0
        self.prev_ma = 0.0
    
    def update(self, value: float) -> float:
        if len(self.queue) >= self.window_size:
            self.running_sum -= self.queue.popleft()
        self.queue.append(value)
        self.running_sum += value
        self.prev_ma = self.ma
        self.ma = self.running_sum / len(self.queue)
        return self.ma

# TA-Lib版
class MovingAverageTA:
    def __init__(self, window_size: int):
        self.window_size = window_size
        self.buffer = deque(maxlen=window_size)
        self.ma = 0.0
        self.prev_ma = 0.0
    
    def update(self, value: float) -> float:
        self.buffer.append(value)
        if len(self.buffer) >= self.window_size:
            self.prev_ma = self.ma
            buffer_array = np.array(self.buffer, dtype=float)
            self.ma = stream.SMA(buffer_array, timeperiod=self.window_size)
        return self.ma

# ベンチマーク
def benchmark(ma_class, iterations=100000):
    ma = ma_class(30)
    start = time.perf_counter()
    for i in range(iterations):
        ma.update(float(i))
    elapsed = time.perf_counter() - start
    return elapsed

# 実行
time_custom = benchmark(MovingAverage)
time_talib = benchmark(MovingAverageTA)

print(f"現在の実装: {time_custom:.4f}秒")
print(f"TA-Lib版:   {time_talib:.4f}秒")
print(f"速度比:     {time_talib/time_custom:.2f}倍遅い")

デイトレ・アプリを稼働させている Intel N150 搭載の Windows 11 PC 上でのベンチマークの結果は下記のとおりでした。残念ながら Python だけで記述したクラスの方が全然速いという結果になりました。

現在の実装: 0.0263秒
TA-Lib版:   0.5771秒
速度比:     21.98倍遅い

参考サイト

  1. TA-Lib - Technical Analysis Library
  2. TA-Lib/ta-lib: TA-Lib (Core C Library)
  3. TA-Lib/ta-lib-python: Python wrapper for TA-Lib
  4. TA-Lib · PyPI

 

ブログランキング・にほんブログ村へ bitWalk's - にほんブログ村 にほんブログ村 IT技術ブログ オープンソースへ
にほんブログ村

オープンソース - ブログ村ハッシュタグ
#オープンソース



このエントリーをはてなブックマークに追加

2025-11-07

【備忘録】VWAP の算出

VWAP(Volume Weighted Average Price, 売買高加重平均価格)とは、当日の東京証券取引所のオークション市場で成立した価格を価格毎の売買高で加重平均した価格をいいます。VWAP は、より取引実態に近い平均的な約定値段として、主に機関投資家の執行価格の目標値として用いられています。

日本取引所グループの用語集 [1] より引用

東証の取引時間中、特定銘柄について 1 秒間隔で株価と出来高(累計)を取得して分析していますが、生成 AI (Microsoft Copilot) に VWAP の算出と活用方法についてアドバイスをもらったので、備忘録にまとめました。

VWAP の計算式

英語版の Wikipedia [2] に VWAP の計算式が示されていたので、それを引用して株価にあてはめました。

\[ P_{VWAP} = \frac{\sum_j {P_j \times Q_j}}{\sum_j Q_j} \]
  • \(P_{VWAP}\)  : VWAP(売買高加重平均価格)
  • \(P_j\) : 取引\(j\) の株価
  • \(Q_j\) : 取引\(j\) の出来高
  • \(j\) : 定義された期間内に発生する個々の取引

 

Microsoft Copilot にお願いをして、VWAP の活用方法、長所・短所についてまとめてもらいました。

VWAP の活用例

  1. エントリー・エグジットの判断基準
    • VWAP より安く買えれば「割安」、高く売れれば「割高」と判断できる
    • 機関投資家は VWAP 付近で約定することを目指すことが多い
  2. トレンドの中心線として利用
    • VWAP は滑らかに推移するため、価格の上下動を相対的に評価できる
    • GUI 上では基準線として表示されることが多い
  3. アルゴリズム取引の基準価格
    • VWAP は多くのアルゴリズム取引で「目標価格」として使われる
    • 特に大量注文を分割して執行する際に、VWAP を基準にすることで市場への影響を抑える

VWAP の長所

長所 内容
市場の平均的な約定価格を示す 実際の取引に基づいた価格なので信頼性が高い
滑らかでノイズに強い 短期的なスパイクに左右されにくく、トレンド把握に適している
逐次更新が可能 リアルタイムでVWAPを更新できるため、ティックデータにも対応しやすい
機関投資家の行動と親和性が高い 実需に基づいた価格判断が可能

VWAP の短所・注意点

短所 内容
過去のデータに依存する 累積的な指標のため、直近の急変には反応が遅れる
時間帯によって意味が変わる 前場と後場で市場の性質が異なるため、VWAP の解釈も変わることがある
出来高が極端に偏ると歪む 特定の時間帯に出来高が集中すると、VWAP がその価格に引っ張られる
単独では売買シグナルにならない 他の指標(RSI、MACDなど)と組み合わせることで真価を発揮する

まとめ

  • VWAP は、市場の平均的な取引価格を把握するための強力なツールです。
  • 特に短期売買やアルゴリズム取引においては、VWAP を基準にすることで、合理的なエントリー・エグジット判断が可能になります。
  • ただし、VWAP はあくまで「過去の加重平均」であり、未来の価格を予測するものではないことに注意が必要です。
  • 他のテクニカル指標と組み合わせて使うことで、より精度の高いトレード判断ができるでしょう。

JupyterLab でプロット

Excel ファイルの保存したティックデータ(シート名は銘柄コード)を読み込んで、VMAP と、株価との乖離率を算出してプロットした例を示します。

必要なパッケージのインポート

import datetime
import os

import matplotlib.font_manager as fm
import matplotlib.pyplot as plt
import pandas as pd
from matplotlib import dates as mdates

Matplotlib の設定(省略可)

FONT_PATH = "../fonts/RictyDiminished-Regular.ttf"
fm.fontManager.addfont(FONT_PATH)

# FontPropertiesオブジェクト生成(名前の取得のため)
font_prop = fm.FontProperties(fname=FONT_PATH)
font_prop.get_name()

plt.rcParams["font.family"] = font_prop.get_name()
plt.rcParams["font.size"] = 12

ティックデータの読込

Excel ファイルはデータを取得した時刻を UNIX 形式のタイムスタンプに変換して保持していますが、このままででは扱いにくいので、Pandas の日付時刻形式に変換してインデックスにしています。

file = "ticks_20251006.xlsx"
body = os.path.splitext(os.path.basename(file))[0]
path_excel = os.path.join("..", "collection", file)
code = "7011"
df = pd.read_excel(path_excel, sheet_name=code)
df.index = pd.to_datetime([datetime.datetime.fromtimestamp(ts) for ts in df["Time"]])
df

 

VWAP と 株価との乖離率 の算出

常に過去データを扱うのであれば、Pandas でスマートに VMAP を算出できるのですが、リアルタイムでデータを逐次取得することを想定しているので、転用しやすいように敢えてループ処理をしています。

cum_pv = 0.0
cum_vol = 0.0
volume_prev = None
vwap_list = []
vwap_deviation_list = []


# データを逐次取得することを想定して、ループで処理
for price, volume in zip(df["Price"], df["Volume"]):
    if volume_prev is None:
        vol_diff = 0.0
    else:
        # ティックデータの出来高は累積出来高であるため
        vol_diff = volume - volume_prev

    cum_pv += price * vol_diff
    cum_vol += vol_diff
    volume_prev = volume

    # VWAP の算出
    vwap = cum_pv / cum_vol if cum_vol > 0 else price
    vwap_list.append(vwap)

    # 株価と VWAP の乖離率
    vwap_deviation = (price - vwap) / vwap
    vwap_deviation_list.append(vwap_deviation)

df["VWAP"] = vwap_list
df["VWAPdev"] = vwap_deviation_list
df

 

株価と VWAP のプロット

fig, ax = plt.subplots(figsize=(6, 3))

ax.plot(df["Price"], linewidth=1, label="株価")
ax.plot(df["VWAP"], linewidth=1, label="VWAP")
ax.xaxis.set_major_formatter(mdates.DateFormatter("%H:%M"))
ax.set_ylabel("VWAP")
ax.grid()
ax.legend(fontsize=7)
ax.set_title(f"{code} in {file}")

plt.tight_layout()
# plt.savefig(f"{body}_{code}_vwap.png")
plt.show()

 

株価と VWAP の乖離率

fig, ax = plt.subplots(figsize=(6, 3))

ax.plot(df["VWAPdev"], linewidth=1, color="C2", label="VWAP 乖離率")
ax.xaxis.set_major_formatter(mdates.DateFormatter("%H:%M"))
ax.set_ylabel("VWAP 乖離率")
ax.grid()
ax.legend(fontsize=7)
ax.set_title(f"{code} in {file}")

plt.tight_layout()
# plt.savefig(f"{body}_{code}_vwap_dev.png")
plt.show()

 

参考サイト

  1. 用語集 | 日本取引所グループ VWAP
  2. Volume-weighted average price - Wikipedia
  3. pandasでExcelファイル(xlsx, xls)の読み込み(read_excel) | note.nkmk.me

 

ブログランキング・にほんブログ村へ bitWalk's - にほんブログ村 にほんブログ村 IT技術ブログ オープンソースへ
にほんブログ村

オープンソース - ブログ村ハッシュタグ
#オープンソース



このエントリーをはてなブックマークに追加

2025-09-30

日経平均株価の構成銘柄を取得

日経平均株価は、日本経済新聞社が算出・公表している日本の株式市場の代表的な株価指数の一つです。東京証券取引所プライム市場に上場している約 2,000 銘柄の株式のうち、取引が活発で流動性が高い 225 銘柄を、日本経済新聞社が選定し算出します。構成銘柄は 4 月と 10 月の年 2 回、上限各 3 銘柄の定期入れ替えが実施されています。

Wikipedia より引用、編集

日経平均株価の構成銘柄を Python で取得しようと Jupyter Lab 上で、参考サイト [1] に従って試したところ、以下のようにエラーが出て取得できませんでした。

dfs = pd.read_html("https://indexes.nikkei.co.jp/nkave/index/component")
---------------------------------------------------------------------------
HTTPError                                 Traceback (most recent call last)

...
(途中省略)
...

    612 def http_error_default(self, req, fp, code, msg, hdrs):
--> 613     raise HTTPError(req.full_url, code, msg, hdrs, fp)

HTTPError: HTTP Error 403: Forbidden

ところが、端末エミュレータ上で同じ URL を wget コマンドで同じサイトを取得してみたところ、難なく出来てしまいました。

上記 Pandas で読み込むやり方でも、何か工夫をすれば読み込めるのかもしれませんが、とりあえず Python から wget コマンドを実行して、読み込みたいサイトを一旦ローカルファイルに保存してから、そのファイルを Pandas で読み込むことで、やりたかったことをできるようになったので、備忘録にしました。

下記の OS 環境で動作確認をしています。

Fedora Linux Workstation 42 x86_64
Python 3.13.7
beautifulsoup4 4.14.2
html5lib 1.1
JupyterLab 4.4.9
lxml 6.0.2
pandas 2.3.3
wget2 2.2.0-5 (rpm)

サンプル

以下、Jupyter Lab 上で実行することを想定しています。

最初に利用するライブラリをまとめてインポートします。

import os
import subprocess

import pandas as pd

外部コマンドを実行する関数です。ピッタリな用途の関数が公開されていたので、そのまま流用させていただきました。

# Reference:
# https://brightdata.jp/blog/各種ご利用方法/wget-with-python
def execute_command(command):
    """
    Execute a CLI command and return the output and error messages.

    Parameters:
        - command (str): The CLI command to execute.

    Returns:
        - output (str): The output generated by the command.
        - error (str): The error message generated by the command, if any.
    """
    try:
        # execute the command and capture the output and error messages
        process = subprocess.Popen(
            command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE
        )
        output, error = process.communicate()
        output = output.decode("utf-8")
        error = error.decode("utf-8")
        # return the output and error messages
        return output, error
    except Exception as e:
        # if an exception occurs, return the exception message as an error
        return None, str(e)

日経平均株価の構成銘柄をデータフレームで取得する処理です。

# wget コマンドで対象サイトをダウンロード
file = "component"
# ファイルが存在していれば削除 
if os.path.exists(file):
    os.remove(file)
output, error = execute_command(f"wget https://indexes.nikkei.co.jp/nkave/index/{file}")

# 保存された HTML ファイルを Pandas で読み込む
dfs = pd.read_html(file)
# 複数のデータフレームを結合して、コード列でソート
df = pd.concat(dfs).sort_values("コード", ignore_index=True)
df

 

参考サイト

  1. Python, pandasでwebページの表(htmlのtable)をスクレイピング | note.nkmk.me
  2. 構成銘柄一覧 - 日経平均プロフィル

 

ブログランキング・にほんブログ村へ bitWalk's - にほんブログ村 にほんブログ村 IT技術ブログ オープンソースへ
にほんブログ村

オープンソース - ブログ村ハッシュタグ
#オープンソース



このエントリーをはてなブックマークに追加

2025-09-16

Ta-Lib を Python で利用する

TA-Lib, Technical Analysis Library は 2001 年にリリースされ、20 年以上経った今でも広く利用されている著名なアルゴリズムを提供しています。コードは安定しており、長年にわたる検証を経ています。200 以上のテクニカル指標をサポートしており、API は C/C++ で記述されており Python ラッパー (wrapper) も提供されています。TA-Lib は BSD License (BSD-2-Clause license) の元で配布されているオープンソースのライブラリです。

以前は Linux 上で TA-Lib の Python 用パッケージを pip でインストールしてもビルドが必要で、しかもエラーでビルドできませんでした。自力でエラーを解決できなかったので TA-Lib の利用を避けていました。しかし最近の TA-Lib のバージョンの Python 用パッケージでは難なくインストールできることが判りました。

そこで今更ですが TA-Lib の使い方をおぼえようと、Jupyter Lab 上でテクニカル指標のいくつかをプロットしてみたので、備忘録的に内容をまとめました。

下記の OS 環境で動作確認をしています。

Fedora Linux Workstation 42 x86_64
Python 3.13.7
JupyterLab 4.4.7
matplotlib 3.10.6
mplfinance 0.12.10b0
numpy 2.3.3
pandas 2.3.2
ta-lib 0.6.7
yfinance 0.2.65

サンプル

ライブラリをインポート

最初に利用するライブラリをまとめてインポートします。

import matplotlib.font_manager as fm
import matplotlib.pyplot as plt
import mplfinance as mpf
import numpy as np
import pandas as pd
import yfinance as yf
from talib import BBANDS, MACD, MFI, MOM, OBV, RSI, SAR, STOCH

yfinance で日経平均株価指数の過去データを取得

サンプルとして、今年の 1 月から半年間の日足データを取得します。

symbol = "^N225"
ticker = yf.Ticker(symbol)
df = ticker.history(start="2025-01-01", end="2025-07-01", interval="1d")

サンプル期間より少し古いデータからも取得しておきます。これでテクニカル指標を算出して、サンプルの期間の最初から指標がプロットされるようにします。

df2 = ticker.history(start="2024-10-01", end="2025-07-01", interval="1d")

mplfinance でチャートを作成

サンプル期間の日足データをローソク足チャートと出来高の棒グラフを並べてプロットしました。

fig = plt.figure(figsize=(8, 4))
ax = dict()
n = 2
gs = fig.add_gridspec(
    n, 1, wspace=0.0, hspace=0.0, height_ratios=[3 if i == 0 else 1 for i in range(n)]
)
for i, axis in enumerate(gs.subplots(sharex="col")):
    ax[i] = axis
    ax[i].grid()

mpf.plot(
    df,
    type="candle",
    style="default",
    datetime_format="%m/%d",
    xrotation=0,
    ax=ax[0],
    volume=ax[1],
)
ax[0].set_title(f"{ticker.info['longName']} ({symbol})")

plt.tight_layout()
# plt.savefig("screenshots/n225_default.png")
plt.show()

Bollinger bands

過去 20 日間の移動平均、移動標準偏差 +3σ, +2σ, +1σ, mean, -1σ, -2σ, -3σ でボリンジャーバンドを作成しました。

fig, ax = plt.subplots(figsize=(8, 3))

# BBANDS - Bollinger Bands
# upperband, middleband, lowerband = BBANDS(real, timeperiod=5, nbdevup=2, nbdevdn=2, matype=0)
period = 20
mv_upper_1, mv_mean, mv_lower_1 = BBANDS(df2["Close"], period, 1, 1)
mv_upper_2, _, mv_lower_2 = BBANDS(df2["Close"], period, 2, 2)
mv_upper_3, _, mv_lower_3 = BBANDS(df2["Close"], period, 3, 3)

apds = [
    mpf.make_addplot(
        mv_upper_3[df.index],
        width=1,
        color="C0",
        linestyle="dotted",
        label="+3σ",
        ax=ax,
    ),
    mpf.make_addplot(
        mv_upper_2[df.index],
        width=0.9,
        color="C1",
        linestyle="dashdot",
        label="+2σ",
        ax=ax,
    ),
    mpf.make_addplot(
        mv_upper_1[df.index],
        width=0.75,
        color="C2",
        linestyle="dashed",
        label="+1σ",
        ax=ax,
    ),
    mpf.make_addplot(
        mv_mean[df.index],
        width=1,
        color="C3",
        linestyle="solid",
        label="Mean",
        ax=ax,
    ),
    mpf.make_addplot(
        mv_lower_1[df.index],
        width=0.75,
        color="C4",
        linestyle="dashed",
        label="-1σ",
        ax=ax,
    ),
    mpf.make_addplot(
        mv_lower_2[df.index],
        width=0.9,
        color="C5",
        linestyle="dashdot",
        label="-2σ",
        ax=ax,
    ),
    mpf.make_addplot(
        mv_lower_3[df.index],
        width=1,
        color="C6",
        linestyle="dotted",
        label="-3σ",
        ax=ax,
    ),
]
mpf.plot(
    df,
    type="candle",
    style="default",
    addplot=apds,
    datetime_format="%m/%d",
    xrotation=0,
    update_width_config=dict(candle_linewidth=0.75),
    ax=ax,
)
ax.grid()
ax.legend(fontsize=7)
ax.set_title(
    f"{ticker.info['longName']} ({symbol})\nwith Bollinger Bands (period={period}days)"
)

plt.tight_layout()
# plt.savefig("screenshots/n225_talib_bbands.png")
plt.show()

Parabolic SAR

AF step=0.02, max=0.2 で Parabolic SAR をプロットしました。上昇下降トレンドの情報が無いので、灰色の丸点でプロットしました。

fig, ax = plt.subplots(figsize=(8, 3))

# SAR - Parabolic SAR
# real = SAR(high, low, acceleration=0, maximum=0)
af_step = 0.02
af_max = 0.2
sar = SAR(df2["High"], df2["Low"], af_step, af_max)

apds = [
    mpf.make_addplot(
        sar[df.index],
        type="scatter",
        marker='o',
        markersize=3,
        color="darkgray",
        ax=ax,
    ),
]
mpf.plot(
    df,
    type="candle",
    style="default",
    addplot=apds,
    datetime_format="%m/%d",
    xrotation=0,
    update_width_config=dict(candle_linewidth=0.75),
    ax=ax,
)
ax.grid()
ax.set_title(
    f"{ticker.info['longName']} ({symbol})\nwith Parabolic SAR (AF step={af_step}, max={af_max})"
)

plt.tight_layout()
# plt.savefig("screenshots/n225_talib_sar.png")
plt.show()

Momentum

過去 10 日間のデータでモメンタムを算出しました。

fig = plt.figure(figsize=(8, 4))
ax = dict()
n = 2
gs = fig.add_gridspec(
    n, 1, wspace=0.0, hspace=0.0, height_ratios=[2 if i == 0 else 1 for i in range(n)]
)
for i, axis in enumerate(gs.subplots(sharex="col")):
    ax[i] = axis
    ax[i].grid()

# MOM - Momentum
# real = MOM(real, timeperiod=10)
period = 10
mom = MOM(df2["Close"], period)
apds = [
    mpf.make_addplot(
        mom[df.index],
        width=1,
        color="C0",
        linestyle="solid",
        ax=ax[1],
    ),
]
mpf.plot(
    df,
    type="candle",
    style="default",
    addplot=apds,
    datetime_format="%m/%d",
    xrotation=0,
    ax=ax[0],
)
ax[1].set_ylabel("Momentum")
ax[0].set_title(
    f"{ticker.info['longName']} ({symbol})\nwith Momentum (period={period}days)"
)

plt.tight_layout()
# plt.savefig("screenshots/n225_talib_mom.png")
plt.show()

RSI, Relative Strength Index

過去 14 日間のデータで RSI を算出しました。

fig = plt.figure(figsize=(8, 4))
ax = dict()
n = 2
gs = fig.add_gridspec(
    n, 1, wspace=0.0, hspace=0.0, height_ratios=[2 if i == 0 else 1 for i in range(n)]
)
for i, axis in enumerate(gs.subplots(sharex="col")):
    ax[i] = axis
    ax[i].grid()

# RSI - Relative Strength Index
# real = RSI(real, timeperiod=14)
period = 14
rsi = RSI(df2["Close"], period)
apds = [
    mpf.make_addplot(
        rsi[df.index],
        width=1,
        color="C0",
        linestyle="solid",
        ax=ax[1],
    ),
]
mpf.plot(
    df,
    type="candle",
    style="default",
    addplot=apds,
    datetime_format="%m/%d",
    xrotation=0,
    ax=ax[0],
)
ax[0].set_title(f"{ticker.info['longName']} ({symbol})\nwith RSI (period={period}days)")
ax[1].set_ylabel("RSI")
ax[1].set_ylim(0, 100)
ax[1].axhline(30, color="black", linewidth=0.5)
ax[1].axhline(70, color="black", linewidth=0.5)

plt.tight_layout()
# plt.savefig("screenshots/n225_talib_rsi.png")
plt.show()

Stochastic oscillator

スローストキャスティクスをデフォルトのパラメータのままでプロットしています。

fig = plt.figure(figsize=(8, 4))
ax = dict()
n = 2
gs = fig.add_gridspec(
    n, 1, wspace=0.0, hspace=0.0, height_ratios=[2 if i == 0 else 1 for i in range(n)]
)
for i, axis in enumerate(gs.subplots(sharex="col")):
    ax[i] = axis
    ax[i].grid()

# STOCH - Stochastic
# slowk, slowd = STOCH(high, low, close, fastk_period=5, slowk_period=3, slowk_matype=0, slowd_period=3, slowd_matype=0)
slowk, slowd = STOCH(df2["High"], df2["Low"], df2["Close"])

apds = [
    mpf.make_addplot(
        slowk[df.index],
        width=1,
        color="C0",
        linestyle="solid",
        label="Slow%K",
        ax=ax[1],
    ),
    mpf.make_addplot(
        slowd[df.index],
        width=1,
        color="C1",
        linestyle="solid",
        label="Slow%D",
        ax=ax[1],
    ),
]
mpf.plot(
    df,
    type="candle",
    style="default",
    addplot=apds,
    datetime_format="%m/%d",
    xrotation=0,
    ax=ax[0],
)
ax[0].set_title(f"{ticker.info['longName']} ({symbol})\nwith Stochastic oscillator")
ax[1].set_ylabel("Stochastic")
ax[1].set_ylim(0, 100)
ax[1].axhline(20, color="black", linewidth=0.5)
ax[1].axhline(80, color="black", linewidth=0.5)
ax[1].legend(fontsize=7)

plt.tight_layout()
# plt.savefig("screenshots/n225_talib_stoch.png")
plt.show()

MACD, Moving Average Convergence Divergence

MACD もデフォルトのパラメータでプロットしています。MACD のヒストグラムは正負で色を変えたかったのですが、すぐに出来なかったので単色にしてしまいました。

fig = plt.figure(figsize=(8, 4))
ax = dict()
n = 2
gs = fig.add_gridspec(
    n, 1, wspace=0.0, hspace=0.0, height_ratios=[2 if i == 0 else 1 for i in range(n)]
)
for i, axis in enumerate(gs.subplots(sharex="col")):
    ax[i] = axis
    ax[i].grid()

# MACD - Moving Average Convergence/Divergence
# macd, macdsignal, macdhist = MACD(real, fastperiod=12, slowperiod=26, signalperiod=9)
period_fast = 12
period_slow = 26
period_signal = 9
macd, signal, macdhist = MACD(df2["Close"], period_fast, period_slow, period_signal)

apds = [
    mpf.make_addplot(
        macd[df.index],
        width=1,
        color="C0",
        linestyle="solid",
        label="MACD",
        ax=ax[1],
    ),
    mpf.make_addplot(
        signal[df.index],
        width=1,
        color="C1",
        linestyle="solid",
        label="Signal",
        ax=ax[1],
    ),
    mpf.make_addplot(
        macdhist[df.index],
        type="bar",
        color="C2",
        ax=ax[1],
    ),
]
mpf.plot(
    df,
    type="candle",
    style="default",
    addplot=apds,
    datetime_format="%m/%d",
    xrotation=0,
    ax=ax[0],
)
ax[0].set_title(
    f"{ticker.info['longName']} ({symbol})\nwith MACD [{period_fast}, {period_slow}, {period_signal}]"
)
ax[1].set_ylabel("MACD")
ax[1].legend(fontsize=7)

plt.tight_layout()
# plt.savefig("screenshots/n225_talib_macd.png")
plt.show()

OBV, On Balance Volume

OBV は終値と出来高から算出する指標です。

fig = plt.figure(figsize=(8, 5))
ax = dict()
n = 3
gs = fig.add_gridspec(
    n, 1, wspace=0.0, hspace=0.0, height_ratios=[2 if i == 0 else 1 for i in range(n)]
)
for i, axis in enumerate(gs.subplots(sharex="col")):
    ax[i] = axis
    ax[i].grid()

# OBV - On Balance Volume
# real = OBV(close, volume)
obv = OBV(df2["Close"], df2["Volume"])

apds = [
    mpf.make_addplot(
        obv[df.index],
        width=1,
        color="C0",
        linestyle="solid",
        ax=ax[2],
    ),
]
mpf.plot(
    df,
    type="candle",
    style="default",
    addplot=apds,
    datetime_format="%m/%d",
    xrotation=0,
    ax=ax[0],
    volume=ax[1],
)
ax[0].set_title(f"{ticker.info['longName']} ({symbol})\nwith OBV")
ax[2].set_ylabel("OBV")

plt.tight_layout()
# plt.savefig("screenshots/n225_talib_obv.png")
plt.show()

MFI, Money Flow Index

MFI も、株価と出来高から算出する指標です。

fig = plt.figure(figsize=(8, 5))
ax = dict()
n = 3
gs = fig.add_gridspec(
    n, 1, wspace=0.0, hspace=0.0, height_ratios=[2 if i == 0 else 1 for i in range(n)]
)
for i, axis in enumerate(gs.subplots(sharex="col")):
    ax[i] = axis
    ax[i].grid()

# MFI - Money Flow Index
# NOTE: The MFI function has an unstable period.
# real = MFI(high, low, close, volume, timeperiod=14)
period = 14
mfi = MFI(df2["High"], df2["Low"], df2["Close"], df2["Volume"], period)

apds = [
    mpf.make_addplot(
        mfi[df.index],
        width=1,
        color="C0",
        linestyle="solid",
        ax=ax[2],
    ),
]
mpf.plot(
    df,
    type="candle",
    style="default",
    addplot=apds,
    datetime_format="%m/%d",
    xrotation=0,
    ax=ax[0],
    volume=ax[1],
)
ax[0].set_title(f"{ticker.info['longName']} ({symbol})\nwith MFI (period={period}days)")
ax[2].axhline(20, color="black", linewidth=0.5)
ax[2].axhline(80, color="black", linewidth=0.5)
ax[2].set_ylabel("MFI")
ax[2].set_ylim(0, 100)

plt.tight_layout()
# plt.savefig("screenshots/n225_talib_mfi.png")
plt.show()

参考サイト

  1. TA-Lib - Technical Analysis Library
  2. TA-Lib/ta-lib: TA-Lib (Core C Library)
  3. TA-Lib/ta-lib-python: Python wrapper for TA-Lib
  4. TA-Lib · PyPI

 

ブログランキング・にほんブログ村へ bitWalk's - にほんブログ村 にほんブログ村 IT技術ブログ オープンソースへ
にほんブログ村

オープンソース - ブログ村ハッシュタグ
#オープンソース



このエントリーをはてなブックマークに追加

2025-01-26

【備忘録】Excel VBA で平均足を算出

VBA, Visual Basic for Applications は、マイクロソフト社が Microsoft Visual Basic を、同社製品の Microsoft Office に搭載したものです。VBA を使用することで、Excel、Access、Word、Outlook、PowerPoint など、Office のアプリケーション・ソフトウェアの機能をカスタマイズしたり、拡張したりすることができます。

Wikipedia より引用、編集

楽天証券に口座を開設してトレーディングをしているので、同社が提供しているトレーディングツール「マーケットスピード II [1]」を利用しています。

マーケットスピード II は高機能なのでトレーディングツールとして申し分ないのですが、データを取得して自分で解析やカスタマイズした処理をしたいので、マーケットスピード II の機能(の一部)を Excel 上で実現できるアドイン「マーケットスピード II RSS [2]」(以下 RSS と呼びます)も利用して、Excel 上でデータの加工などをしています。

RSS の RssChart 関数を利用すれば簡単に 始値-高値-安値-終値 の四本値データ(+出来高)をリアルタイムで取得できます。リアルタイムと言っても、例えば1分足の場合、1分毎に更新されたデータを1行下に追加するという動作です。

マーケットスピード II でチャート上に表示できる平均足をじっくり評価したかったのですが、残念ながら平均足データを取得する関数は RSS に用意されていません。そこで、四本値データから平均足を算出する VBA マクロを作成しました。

Excel VBA で 平均足を算出

RSS の RssChart 関数が Excel シートへリアルタイムで流し込んでくれる東証の銘柄の1分足データから、平均足を算出、右側に追記する VBA マクロです。

下記の OS 環境で動作確認をしています。

Microsoft Windows 11 Home 24H2
Microsoft Excel 2024 MSO 64 ビット

VBA でのアプローチ

下記の赤い領域に新しい平均足の値 (H_Open, H_High, H_Low, H_Close) を算出するために、赤い領域を含む灰色の領域 (Range) を Variant 配列に転記して、平均足を算出処理するマクロへ渡します。

平均足を算出するために使用する範囲

サンプルでは、算出後の配列をそのまま元の領域 (Range) へ戻しています。このやり方はシンプルですが、バグにより本来変更してはならない部分が書き換えられてしまうリスクがあります。

VBA マクロの構成

今回のマクロの構成は以下のようになっています。

 

実装環境から抜き出して、それをサンプル用として1つのモジュールにまとめなかったため、動作確認用サンプルは複数のモジュールにまたがってしまっています。あらかじめご了承ください。

平均足の算出処理

平均足の算出処理は、標準モジュール ModTechnical の Sub プロシージャ CalcHeikinAshi を呼び出します。

平均足の算出は、参考サイト [3] にある平均足の説明に沿っています。説明文を VBA コード内のコメントに流用させていただきました。

標準モジュール ModTechnical
Option Explicit


' ### プライベート定数(モジュールレベル) ####################################

Private Const P_OPEN As Long = 1
Private Const P_HIGH As Long = 2
Private Const P_LOW As Long = 3
Private Const P_CLOSE As Long = 4
Private Const P_VOLUME As Long = 5
Private Const H_OPEN As Long = 6
Private Const H_HIGH As Long = 7
Private Const H_LOW As Long = 8
Private Const H_CLOSE As Long = 9


' _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_
'
' 平均足の算出
'
' 【参考サイト】
' https://marketspeed.jp/ms2/onlinehelp/ohm_007/ohm_007_05.html
'
' _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_
Sub CalcHeikinAshi(arr As Variant, Optional Is1st As Boolean = False)
    
    If Is1st Then
        ' 2本目の平均足:前日の平均足がないため、始値を下記値より算出する
        ' 始値 = (前日の始値 + 前日の高値 + 前日の安値 + 前日の終値) / 4
        arr(2, H_OPEN) = _
            (arr(1, P_OPEN) + arr(1, P_HIGH) + arr(1, P_LOW) + arr(1, P_CLOSE)) / 4
    Else
        ' 始値=(前日の平均足の始値+前日の平均足の終値)/2
        arr(2, H_OPEN) = (arr(1, H_OPEN) + arr(1, H_CLOSE)) / 2
    End If
    
    ' 終値=(当日の始値+当日の高値+当日の安値+当日の終値)/4
    arr(2, H_CLOSE) = _
        (arr(2, P_OPEN) + arr(2, P_HIGH) + arr(2, P_LOW) + arr(2, P_CLOSE)) / 4
    
    ' 陰線:始値>=終値
    ' 陽線:始値<終値
    ' 平均足の高値と安値は、当日の高値と安値を用いる。
    
    If arr(2, H_OPEN) >= arr(2, H_CLOSE) And arr(2, P_HIGH) < arr(2, H_OPEN) Then
        ' 但し、平均足が陰線で当日の高値<平均足の始値の場合、
        ' 平均足の高値=平均足の始値とする。
        arr(2, H_HIGH) = arr(2, H_OPEN)
    Else
        ' 当日の高値
        arr(2, H_HIGH) = arr(2, P_HIGH)
    End If
    
    If arr(2, H_OPEN) < arr(2, H_CLOSE) And arr(2, P_LOW) > arr(2, H_OPEN) Then
        ' 但し、平均足が陽線で当日の安値>平均足の始値の場合、
        ' 平均足の安値=平均足の始値とする。
        arr(2, H_LOW) = arr(2, H_OPEN)
    Else
        ' 当日の安値
        arr(2, H_LOW) = arr(2, P_LOW)
    End If

End Sub

動作確認

動作確認のサンプルを示しました。テスト用のマクロですが、用途の事情で擬似的に1秒間隔でループを回したかったので、少し長くなってしまいました。

標準モジュール ModCommon
Option Explicit


' ### 定 数 ##################################################################

' 取引時間関連
Public Const T_OPEN_MKT As Date = "09:00:00"
Public Const T_HEIKIN_START As Date = "09:02:00"
Public Const T_LUNCH_START As Date = "11:30:00"
Public Const T_LUNCH_END As Date = "12:30:00"
Public Const T_HEIKIN_END As Date = "15:24:00"
Public Const T_CLOSE_MKT As Date = "15:30:00"

市場が開いて 9:00 の1分足データが確定するのは 9:01 以降です。また最初 (9:00) の1分足データに対しては平均足を算出できません。9:01 の1分足データが確定するのは 9:02 以降になります。ですので、平均足を算出するのは T_HEIKIN_START で指定した 9:02 になります。

なお、ここでは処理をシンプルにするために RssChart 関数は、時刻が 0 秒になったら直ちに直前の1分足データをシートに書き込むものとし、かつ、株価は 9:00 に寄り付いているものとしています。

汎用関数は標準モジュール ModFunc にまとめてあります。この動作確認用サンプルでは GetPrevMinute 関数しか使いませんが、依存している関数も含めています。

標準モジュール ModFunc
Option Explicit


' ### Function 関数 ###########################################################


' _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_
'
' 現在の時刻 (HH:MM:SS) を HH:MM 形式の文字列で取得
'
' _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_
Public Function GetCurrentMinute(timeNow As Date) As String
    Dim StrHH As String
    Dim StrMM As String

    StrHH = Format(Hour(timeNow), "00")
    StrMM = Format(Minute(timeNow), "00")
    
    GetCurrentMinute = StrHH & ":" & StrMM

End Function


' _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_
'
' 一分前の時刻を HH:MM 形式の文字列で取得
'
' _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_
Public Function GetPrevMinute(timeNow As Date) As String
    Dim timePrev As Date

    timePrev = DateAdd("n", -1, timeNow)
    GetPrevMinute = GetCurrentMinute(timePrev)

End Function

動作確認用のマクロはワークシートに記述しています。

Microsoft Excel Objects Sheet1
Option Explicit


' ### プライベート定数(モジュールレベル) ####################################


' 列関連
Private Const P_TIME As Long = 5
Private Const P_OPEN As Long = 6
Private Const P_HIGH As Long = 7
Private Const P_LOW As Long = 8
Private Const P_CLOSE As Long = 9
Private Const P_VOLUME As Long = 10
Private Const H_OPEN As Long = 11
Private Const H_HIGH As Long = 12
Private Const H_LOW As Long = 13
Private Const H_CLOSE As Long = 14

Private Is1st As Boolean        ' 最初の処理かを判定するフラグ


' ### Sub プロシージャ ########################################################


' _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_
'
' 平均足テスト
'
' _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_
Sub TestHeikinAshi()
    Dim timeNow As Date
    Dim strTargetTime As String ' 検索するターゲット時刻
    Dim RangeCol As Range       ' 検索レンジ(1列)
    Dim foundObj As Range       ' 検索結果を格納するレンジ
    Dim RangeData As Range      ' データ範囲
    Dim rowLast As Long         ' 最終行
    Dim row1 As Long            ' 平均足算出に使用するレンジの第一行
    Dim row2 As Long            ' 平均足算出に使用するレンジの第二行
    Dim arrHeikin As Variant    ' 平均足算出処理に渡す配列

    ' シートの初期化
    Call SheetInit

    timeNow = T_OPEN_MKT
    Do While timeNow <= T_CLOSE_MKT
        If T_HEIKIN_START <= timeNow And timeNow <= T_HEIKIN_END And Second(timeNow) = 0 Then
            strTargetTime = GetPrevMinute(timeNow)
            
            ' 時刻列の最終行を取得
            rowLast = Cells(1, P_TIME).End(xlDown).Row
            ' 検索レンジ(1列)を設定
            Set RangeCol = Range(Cells(1, P_TIME), Cells(rowLast, P_TIME))
            ' 検 索
            Set foundObj = RangeCol.Find(strTargetTime, LookAt:=xlWhole)
            ' 検索結果による処理
            If Not foundObj Is Nothing Then
                ' 検索結果が有る場合は検索セルの行を取得
                ' ※ 検索する時系列は重複が無いことを前提にしている
                row2 = foundObj.Row
                row1 = row2 - 1

                ' 平均足算出に必要なレンジを配列へ転記
                arrHeikin = Range(Cells(row1, P_OPEN), Cells(row2, H_CLOSE)).Value

                ' 平均足の算出
                If Is1st Then
                    Call CalcHeikinAshi(arrHeikin, Is1st)
                    Is1st = False
                Else
                    Call CalcHeikinAshi(arrHeikin)
                End If

                ' 平均足算出結果を元のレンジへ転記
                Range(Cells(row1, P_OPEN), Cells(row2, H_CLOSE)).Value = arrHeikin

            End If

        End If
        
        ' 現在時刻を1秒進める
        timeNow = DateAdd("s", 1, timeNow)
    
    Loop

End Sub


' _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_
'
' シートの初期化
'
' _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_
Sub SheetInit()
    Dim xlLastRow As Long  ' Excel自体の最終行
    Dim rowLast As Long    ' 最終行
    Dim RangeData As Range ' データ範囲
    
    ' 以前に算出した平均足データの消去
    xlLastRow = Cells(Rows.Count, P_TIME).Row          ' Excelの最終行を取得
    rowLast = Cells(xlLastRow, P_TIME).End(xlUp).Row ' 時刻列の最終行を取得
    If rowLast > 1 Then
        Set RangeData = Range(Cells(2, H_OPEN), Cells(rowLast, H_CLOSE))
        RangeData.ClearContents
    End If

    ' 最初の処理かを判定するフラグの初期化
    Is1st = True

End Sub

Excel 上で思うようにローソク足チャートを描画できなかったので、JupyterLab 上にチャートをプロットしました。ここでは Python のコードは割愛します。4本値を用いた通常のローソク足チャートと平均足データによるローソク足チャートを並べました。

通常のローソク足チャート

平均足データのローソク足チャート

サンプルシート

以上のコード、シートを含む Excel ファイルを下記からダウンロードできます。ご参考まで。

sample_heikinashi.xlsm

参考サイト

  1. マーケットスピード II | 楽天証券のトレーディングツール
  2. マーケットスピード II RSS | 楽天証券のトレーディングツール
  3. テクニカル指標/チャート形状 | マーケットスピード II オンラインヘルプ | 楽天証券のトレーディングツール

 

ブログランキング・にほんブログ村へ bitWalk's - にほんブログ村 にほんブログ村 IT技術ブログ オープンソースへ
にほんブログ村

オープンソース - ブログ村ハッシュタグ
#オープンソース



このエントリーをはてなブックマークに追加