VBA投資楽天RSS2

Application.Ontimeを使ってループ処理を行う。

VBA
スポンサーリンク

イメージしにくく、とっつきにくく、バグると面倒

 マーケットスピード2 RSS(楽天RSS2)では通常のdoeventsやwait等でのループを使用するとエクセル上の関数の更新が止まってしまうため、Application.Ontimeを使用する必要があります。通常のものとループのイメージが異なるため、専用に組みなおす必要が出てきます。まずは通常のものとどこが違うのかを見ていきます。
 通常の一定時間ごとに処理を行う場合のループですとこのような形になるかと思います。

oldtime=Now()
Do
	doevents
	If oldtime + TimeValue("00:00:02") <= Now() Then
		'定期的な処理をここへ書く
		oldtime=Now()
	Endif
Loop

一つで完結するためわかりやすいのですが、マーケットスピード2 RSSにおいては動作しません。そのため以下のようにApplication.Ontimeを使用します。※ScheduleTime はグローバル変数として登録します。

Sub Main_start()
'スタート用。これをまず呼ぶ
'イニシャル処理等はこっちで行う
'↓メインを呼び出す
ScheduleTime = Now() + TimeValue("00:00:10")
Application.OnTime ScheduleTime, "Main"

End Sub

Sub Main_end()
'終了用
Application.OnTime ScheduleTime, "Main", , False

End Sub

Sub Main()
'メイン
'定期的な処理をここへ書く
'自分で自分を呼び出す↓
ScheduleTime = Now() + TimeValue("00:00:10")
Application.OnTime ScheduleTime, "Main"
      
End Sub

 開始用のプロシージャ(Sub~End Subのくくり)、終了用のプロシージャ、メイン処理用のプロシージャが必要になります。開始用のプロシージャでイニシャル処理等を行い、メイン処理用のプロシージャには定期的に処理するもののみ書きます。20~21行目で10秒後にMain(メイン処理)自身を再度呼び出すようタスクに登録されます。
 こうすることによってループが発生します。止める際はMain_end()を呼び出します。これはApplication.OnTimeが(引数1:時間、引数2:プロシージャ名、引数3:プロシージャを実行できる最終時刻、引数4:Trueならタスク登録、Falseならタスク削除)となっており、タスクに登録されているプロシージャを削除します。引数1と2が完全一致する必要があるため(特に1)、登録時間(ScheduleTime)をグローバルに持つ必要があります。緊急時や、ループの途中で止まってもいいならEscキーを押し続けるのも手です。バグると想定外の動作や意図しないときに動作になりがちのため、まずは止める方法とその処理の流れをマスターしましょう

処理の違いとしては簡単には上の図のようになります。現実にはDoeventsは秒間千~一万回くらい動いており、Application.Ontimeは1回のみで、黄色で書いているところ(処理中のタイミング)は実際にはないに等しく、ほぼすべての時間をアイドル状態で過ごすことができます。これによりマーケットスピード2 RSS(楽天RSS2)においてもExcelのシート関数の値を更新しつつ、VBAで監視、発注を行うことができます。
 VBAでApplication.Ontimeを使ってループ処理を行う手法について紹介してある本は少なく、↓のようなぶ厚めの非初心者向け本にやっと掲載されているレベル。この本は作成方法から止め方まで丁寧に書いてあり良いです。この処理に自信のない方は参考にするといいと思います。

コメント

  1. 匿名 より:

    上記の質問をしたものです。
    回答ありがとうございました。
    私はデイトレで、常時2000弱の銘柄を監視するのに使いたいのですが、
    最低1秒間隔で、それプラス更新の待ち時間があると銘柄数を絞らないとダメそうですね。

    差し支えなければ、kotatsuさんが普段、何銘柄を監視しているか教えていただくことはできますか?

    • kotatsu kotatsu より:

      コメントありがとうございます。
      調べたところ、application.ontimeでは1秒未満の指定はできないようですが、
      WindowsAPIのSetTimerを使うことでミリ秒で同様の動作が可能となるようです。
      https://excel-ubara.com/excelvba4/EXCEL299.html

      ただ、確認していたところ、私の環境ではそもそも楽天RSS2から送られてくるデータが1秒間隔より短く
      なりませんでした。2000弱の銘柄となるとデータ量が多く、1秒でデータ更新が安定するのかもよくわかっていないですが…

      データの変化した瞬間をタッチの差で取引行うという意味ではこちらの関数に置き換えるメリットもあるかもしれないです。
      (参考リンクにも記載ありますが、バグると厄介そうではあります。)

      私が監視しているのは15~20程度の銘柄になります。

  2. 匿名 より:

    はじめまして。
    私もエクセルVBAとRSS2で自動ツールを作成しており、
    RSS2の数値が更新されない問題の解決方法について調べていたところ、
    こちらの記事に辿り着きました。

    こちらの記事を参考にさせていただきdoloopからontimeに変更したところ、
    無事、数値の取得ができました。ありがとうございました。

    私の環境ではontimeの設定を1秒後以降の動作にしないと数値が更新されないのですが、
    kotatsuさんもそのような時間設定でしょうか?
    (できるだけ待ち時間を減らしたいのですが)

    • kotatsu kotatsu より:

      コメントありがとうございます。動作するようになって何よりです。
      application.ontimeの仕様上、1秒未満は0秒扱いでうまく行かない(doloop的な動き)ようです。つまり最短設定で1秒になります。
      私は日中いないので動作しているところをまともにデバッグできないため、無難に動作してもらいたく10秒周期にしています。

タイトルとURLをコピーしました