本稿ではIE操作で証券会社に注文を発注する方法を解説しています。
ブラウザはIE(もしくはエッジのIEモード)限定です。
残念ながらIEの寿命はあとわずかで尽きようとしています。
ということで、このような段階でのIE操作による注文方法の解説にどれだけの意義があるのかどうかはわかりませんが、将来、SeleniumBasic等での操作に移行するにしても、たぶん記述方法が少々異なるぐらいでやらなければならないことは一緒ですから、その際のご参考にはなるだろうということで取り敢えずはここでまとめておきます。
まず、最初に、
証券会社のログイン画面の呼び出しから注文完了までを自動で処理するためにはどのような知識が必要なのかをみていきましょう。
①ログイン画面の表示に必要な知識は?
画面表示はVBAだけでは実現できないのでIEとの連携が必要となってきます。
その際のVBAとIEとのやりとりはオブジェクトをやり取りするための規格であるOLE(Object Linking and Embedding)オートメーション規格を利用して実現します。
②ログイン画面でのログイン情報入力と送信ボタン押下から注文完了までで必要な知識は?
ログイン画面、人の作業であればIDやパスワードの入力欄やどれが送信ボタンかは一目瞭然ですから迷いもなくIDとパスワードを入力し送信ボタンを押すだけです。
しかし自動となるとまず画面のHTMLのコードの中からIDとパスワードを入力するコードと送信ボタンのコードを探し出してやらなければなりませんし、特定した要素にデータを代入せよとか特定した送信ボタンを押せという指示も出してやらなければなりません。
その他の画面、例えばメニュー画面でも注文画面でも対象となる項目が異なるだけでやるべきことは一緒で、要素の特定と取得そして取得した要素の操作です。
その際に必要となってくるのが、
WEBページ作成用言語のHTML(HyperTextMakeupLanguage)とHTMLの要素にアクセスして取得や操作を実現する仕組みであるDOM(DocumentObjectModel)の知識です。
つまり、Excel VBAロボット作成に必須の知識はExcelとExcel VBAを除けば、
●OLEオートメーション
●HTML
●DOM
この3つの知識です。
略字ばかりが並んでいますのでなんとなく難しそうな印象を持たれてしまう方もいらっしゃるかもしれませんが、ロボット作成に必要なところはごくごく基礎的なところだけです。
では、ログイン画面の表示方法から順に解説していきます。
ログイン画面を表示する
既述ですが、画面表示はOLE(Object Linking and embedding)オートメーション規格を利用したIE操作で実現します。
画面を表示する方法には事前にIEを参照できるようにしておく事前バインディングと実行時に参照できるようにする実行時バインディングの2通りの方法がありますが、ここでは後者という前提で説明していきます。
下記がログイン画面を表示する際の一般的なコードです。↓
画面表示の際のお決まりのコードです。
CreateObject関数でIEへの参照を実現しSetステートメントでIEオブジェクトを変数に代入、画面を可視化し、NavigateメソッドでIEに画面表示を指示、その後のコードは画面表示が完了したか否かをチェックしています。
画面表示完了チェックのコードの最初のループはIEの処理の終了を待つループで、次のループはドキュメントの読み込みの完了を待つループです。
ループ中のDoEventsはいったんOSに制御を渡す命令です。
画面の構造によっては2つのループでは表示完了を確認できない場合があります。
その場合はVBAの実行を一時的に停止するコードを2つのループの下に記述して調整します。
それでもダメな場合はループ内のDoEventsの下に一時的に停止するコードを入れてみて下さい。
ログイン画面の場合は画面構造が単純ですのでほとんど調整する必要はないかと思いますが、注文用画面の場合は2つのチェックではうまくいかないケースも出てきます。
VBAの実行を停止する方法に関してはこちらを参照してください。↓
ちなみに上記コード例では記述していませんが、証券会社への注文処理が完了し、IEとのやり取りが不要になった場合は必ず次の2行を記述して、IEを終了、設定したIEオブジェクトは解放してください。
objIE.Quit
set objIE = Nothing
また、上記の画面表示サンプルでは、objIEをDimで定義していますが、ロボットファイルを作成する際には同一プロジェクト内であれば使用できるようにトップモジュールの宣言セクションでPublicで定義しておいた方が便利かと思います。
さて、上記処理でログイン画面は表示できましたので、次に処理対象要素の取得方法と操作方法についての解説に入ろうと思うのですが、その前に、要素(エレメント)、タグ、属性とはどのようなものかということだけは把握しておいていただきたいので簡単に解説しておきます。
ご存じの方は飛ばしてください。
要素(エレメント)、タグ、属性について
証券会社のメニュー画面で右クリック、「ページのソース表示」選択でソースを開いてみると、例えば次のようなコードが並んでいるかと思います。
<a href=”先物新規建て画面のURL”>先物新規</a>
メニューを選択した場合、指定されたリンク先に飛ぶコードです。
このコード全体が要素(エレメント)です。
<a href=”先物新規画面のURL”>と</a>がタグで、前者を開始タグ、後者を終了タグといいます。
これから頻繁に出てくるinput要素のように終了タグがもともとない要素や開始タグや終了タグを省略できる要素もあります。
開始タグと終了タグに囲まれている先物新規の部分が要素内容です。
次に開始タグの内容を見ていきましょう。
aの部分が要素名(タグ名)で、href=”先物新規画面のURL”の部分が属性です。
ちなみにaはanchorの略で、a要素の他にアンカー要素という言葉もよく使われます。
属性は要素の性質や特性を指定するために使用され、書式は属性名=値です。
要素名ごとに指定できる属性名は決まっています。
IE操作では要素名(タグ名)、属性名、値等から操作対象要素を特定します。
要素名(タグ名)や属性名は数多く存在しますが、注文時に操作対象となる要素名や属性名はごくわずかですので頭に入れておいていただければと思います。
ロボットファイル作成時に最低認識しておかなければならない要素名(タグ名)はa要素、input要素、select要素、form属性です。
●a要素はリンク先を指定する際に使用され、メニュー画面のメニュー選択時によく使われている要素です。属性として指定されるのはほとんどの場合href属性です。
●input要素はID、パスワード、投資枚数、価格等の入力欄や売か買か、注文方法は成行か指値か逆指値等の選択時に使用されるラジオボタン等を定義する要素です。
input要素のコード例です。↓
<input type=”radio” id=”abc” name=”efg” value=”1″>
input要素に指定される属性で要素の特定によく使用される属性はid属性、name属性、class属性、value属性です。特定した要素への操作方法はType属性の値で判断できます。具体的な操作方法について「要素の操作方法」のところで解説しています。
●select要素はセレクトボックス(いくつかの選択肢から1つを選択する部品)を定義する要素で、注文の有効期限を選択する際によく使われています。
●form要素は、送信ボタン(Submitボタン)の操作にはどのフォームの送信ボタンかを指示しなければなりませんので、その確認のために必要な要素です。
以上、簡単ですが要素、タグ、属性についての解説でした。
それでは具体的な処理方法の解説に入ります。
要素の特定方法
注文発注処理時に処理対象となる要素はa要素、input要素、select要素、この3つの要素にほぼ限定されます。
要素単位で解説した方がわかりやすいと思いますので、まず、a要素の特定方法と操作方法から順に解説していきます。
a要素の場合
メニュー画面のメニュー選択の部分は通常、下記のようにa要素で構成されています。
<a href=”リンク先~”>ログイン画面へ戻る</a>
<a href=”リンク先~”>先物新規</a>
<a href=”リンク先~”>先物決済</a>
<a href=”リンク先~”>先物注文照会</a>
<a href=”リンク先~”>先物建玉一覧</a>
この中から先物新規を特定する場合のコード例です。↓
処理の流れとしては、
objIE.Document.Links.LengthでHTML内のa要素の総数を取得しています。
上の例では5個です。
objIE.Document.Links.Length-1としているのは添え字が0スタートだからです。
添え字に該当するチェック対象の要素のテキスト部分を変数に代入、InStr関数を利用して変数中に”先物新規”という文字列があるかないかをチェック、InStr関数は位置情報を返してくれますから、もしInStr関数の戻り値が0でなければあったということでターゲットの要素と特定、その要素をClickメソッドで操作しています。
メニュー選択はほぼこのパターンで処理できます。
input要素の場合
input要素を特定するにはElementオブジェクトのgetElement~メソッドを使用します。
getElement~メソッドには次のような種類があります。
・getElementByID:id名で特定する
・getElementsByName:name名で特定する
・getElementsByClassName:class名で特定する
・getElementsByTagName:tag名で特定する
同一ID名をHTML内の複数個所で使用することはできないルールになっているのでid名での特定で取得できる要素は1つということでElementと単数形ですが、それ以外は同一名が複数存在する可能性がありますのでElementsと複数形になっています。
要素を特定する際の手順としては、まずid属性の有無を確認します。
有った場合はid名はHTML内で唯一ですので、
objIE.Document.getElementById(“ターゲットのid名”)で特定できます。
ただし、複数個所で同一idを使用してもエラーにはならないのでごくごくたま~に複数存在する場合があります。その場合はname属性等で特定します。
id属性がなかった場合は、name属性の有無を確認します。
name属性があった場合は、
objIE.Document.getElementsByName(“ターゲットのname名”)(添え字)で特定します。
同一name名はHTML内に複数存在する可能性がありますので特定する際には添え字が必要となります。
添え字は0から始まりますので最初の要素であれば(0)、2番目であれば(1)です。
input要素においてはid属性がない場合でもname属性はほぼ100%近くありますからほとんどの要素はここまでで特定できるかと思います。
同一name名が数多く存在する場合は、次のようにinput要素を上から順に検索し、name属性の値とvalue属性の値の一致で特定するような方法もあります。
もしname属性もなかった場合はclass属性の有無を確認し、
有れば、
objIE.Document.getElementsByClassName(“ターゲットのname名”)(添え字)で特定します。
name属性と同様、特定には添え字が必要です。
もしなかった場合ですが、その場合は上記のコーディング例のようにinput要素を検索し、指定されているその他の属性を使用してなんとか特定するしかありません。
select要素の場合
select要素はいくつかの選択肢から1つを選択する際に使用されるセレクトボックスの定義に使用します。
注文画面では注文の有効期限の選択欄でよく使われています。
特定方法はinput要素と同じです。
要素の操作方法
特定した要素の操作方法について、要素別に解説していきます。
a要素の場合
要素の特定方法のコード例にも記述されていますが、操作にはClickメソッドが使用されます。
input要素の場合
注文画面等のinput要素でよく指定されているのは下記のようなtype属性です。
・type=”text“:数値や価格の入力
・type=”password“:パスワード入力
・type=”radio“:ラジオボタン、成行か指値か等の執行条件の選択によく使われるボタン
・type=”checkbox“:注文確認画面を省略しますか?等のチェックに使用される
・type=”submit“:送信ボタン
id、パスワード、注文枚数、価格等の入力欄はValueプロパティを使用して下記のように操作します。
objIE.Document.getElementsByName(“name名”)(添え字).Value = 入力値
ラジオボタンやチェックボックスの場合は下記のようにClickメソッドで操作します。
objIE.Document.getElementsByName(“name名”)(添え字).Click
チェックボックスは下記のようにCheckedプロパティでも操作できますが、
objIE.Document.getElementsByName(“name名”)(添え字).Checked = True
画面の構成によっては不安定になってしまうことがありますのでClickメソッドでの操作の方が確実です。
送信ボタンの場合は下記のようにSubmitメソッドで操作します。
フォームが一つだけの場合や最初のフォームの送信ボタンの操作の場合は
objIE.Document.forms(0).submit
画面が複数のフォームで構成されている場合、例えば3個のフォームで構成されている場合で2つ目のフォームの送信ボタンを操作するのであれば
objIE.Document.forms(1).submit
送信ボタンもボタンですから、name属性等で特定できる場合はClickメソッドでも操作可能です。
select要素
セレクトボックスはselect要素で次の例のように定義されています。
<select id=”ABC” name=”EFG” >
<option value=”20220720″>2022/07/20(水)</option>
<option value=”20220721″>2022/07/21(木)</option>
<option value=”20220722″>2022/07/22(金)</option>
<option value=”20220725″>2022/07/25(月)</option>
<option value=”20220726″>2022/07/26(火)</option>
</select>
操作にはselectedIndexプロパティを使用します。
上記の例で7/25を選択するのであれば、インデックスは0から始まりますから
objIE.Document.getElementById(“ABC”).selectedIndex = 3
となります。
その他の留意事項
ここままでの解説でIE操作の大筋は説明できたかと思いますが、細かい部分に関してはまだまだありそうですので思いついた時に逐次ここで記述していこうかと思います。
画面の建玉枚数を取得する方法(各種メッセージの確認にも使える)
返済注文の際、一括返済を選択できる場合はいいのですが、一括返済がない場合は建玉数量を取得しなければなりません。
その際のコード例です。↓
建玉数量が〇〇枚と枚の前にスペースなしで表示されていることと数量は4桁以下であることが前提です。
返済画面のテキスト部分をinnerTextで取得し変数に格納。
InStr関数で「枚」までの桁数を取得。
枚の2桁手前がスペースの場合、
数量は1桁ということで枚の手前の1桁をMid関数で取得し変数に格納。
枚の2桁手前がスペースでない場合で
枚の3桁手前がスペースなら
数量は2桁ということで枚の手前の2桁をMid関数で取得し変数に格納。
以下、説明は省略します。
検索対象となるキーワードまでの位置を取得し、その手前の情報を取得する処理はだいたい上記コードの応用で対処できます。
上記コードを応用すれば、注文が正常に完了したか否かの確認等にも使えます。↓
ミニの場合のターゲットメジャー限月の位置の取得方法
新規注文時、ラージの場合は最初に表示される限月が直近のメジャー限月ですから問題はないのですが、ミニの場合は処理対象のメジャー限月の表示位置はSQの前後で変化してしまいますから、正しい限月を選択するために常に対象のメジャー限月が何番目に表示されているのかを把握しておくなければなりません。
順番を知る方法は他にもあるとは思いますが、取り敢えずRssIndexMarket関数とMATCH関数を使用すれば簡単に取得できます。
B1からB5までのセル式です。↓
B1セル:=RssIndexMarket(“N225.FUT01.OS”,”限月”)
B2セル:=RssIndexMarket(“N225M.FUT01.OS”,”限月”)
B3セル:=RssIndexMarket(“N225M.FUT02.OS”,”限月”)
B4セル:=RssIndexMarket(“N225M.FUT03.OS”,”限月”)
B5セル:=MATCH(B1,B2:B4,0)
後は順位を格納する変数を設定し、B5の内容を格納。
その変数を利用して対象の限月の位置を特定しClickメソッドで選択します。
例えば、
B5内容を格納した変数がGenNoで、ミニの限月選択の直前までのa要素の数が10個(ページのソース表示を見てカウントする)だったとすれば、
objIE.Document.Links(9 + GenNo).Clickで選択できます。
証券会社ごとに限月の選択画面は異なりますから、上記の処理を基本として各証券会社の画面に対応させます。
通常は限月順位は1~3ですが、メジャー限月前日の夜間セッションの場合、証券会社によっては旧メジャー限月のエリアが残っていて、4番目を選択しなければならないこともありますので注意が必要です。
画面情報を再取得する方法
ある画面からリンク先の画面に飛ぶ際、見た目はリンク先の画面に変わっているにもかかわらずVBAが認識しているのは前画面というケースが極まれにですが発生します。
そのような場合はShellオブジェクトを利用した画面の再読み込みで対処できることがありますので、コード例を掲載しておきます。↓
まとめ
以上、IE操作で証券会社に注文を発注する方法についての解説でした。
証券会社への自動発注というと「難しいのでは」と思われる方も多いのかもしれませんが、処理の流れとしては案外単純だということはご理解をいただけたかと思います。
ただし、実際、作成するとなると細かいレベルではいろいろな壁にぶち当たりますが、根気でググっていけば何かしらの解決策は得られます。
興味を持たれた方はチャレンジしてみてください。
楽天証券マーケットスピードⅡRSSによる注文発注についてはこちらで解説しています。↓