兼業投資家のシステムトレードメモ

兼業投資家のシステムトレードメモ

30代独身の兼業投資家がシストレの話題を中心に書いていく(予定)のブログです。

Twitter:
https://twitter.com/QHs0YUr5QGMbZUQ

開発環境:
岡三RSS/楽天RSS/スクレイピング
.Net(C#)/VB6/Excel VBA/DOS/Shell/Python/AWS/MySQL

Amebaでブログを始めよう!

イザナミでファンダメンタルの検証ができるように準備をしたのでやったことを記します。

 

①欲しいデータをCSV形式で準備する。

 
以下の形式のCSV(カンマ区切り)を作成します。
 1列目:銘柄コード
 2列目:市場
 3列目:日付
 4列目以降:ほしいファンダメンタルデータ
 
1行目はタイトル行にして、2行目以降に実際の数値を記載します。
 
イメージ
 
【注意すべき点】
・データが無い場合はその列に値を出力せずカンマのみとする。
 例 : 2156,JASDAQ,2007/06/21,,,,,,
 
・文字コードは「ShiftJIS」にする。
・改行コードは「CRLF」にする。
・イザナミのサイトには「市場」が省略可と書いてあった(と思う)が省略するとエラーになる。
・イザナミのサイトには「KABU+」というサービスでファンダメンタルを取得する方法が記載されています。
(今回は自作しましたがKABU+を使う方が手間が少ないと思います)
 
 
②イザナミで環境データを有効化する。
 
バックテストの画面でオプションを「売買ルールの条件判断に環境データを使用する」をチェックする。
 
 
③イザナミにデータを取り込む。
 
画面左側の「環境データを使う」タブを有効にして、下部の「+」ボタンを押す。
 
 
ファイルを選択を押して表示されるダイアログを以下の通り選択しOKを押す。
 
ファイル選択ダイアログが表示されるので準備したCSVを選択する。
 
 
④データを確認する。
 
「環境データの表示」ボタンを押してデータを確認する。
データにエラーがあった場合は以下のようなダイアログが表示されるのでCSVの内容を見直す。
※以下は文字コードがUTF8だった際に出たエラー
 
 
⑤データを利用してバックテストする。
 
バックテストの条件として用意したデータが使用できるようになっています。

年初来高値の更新銘柄を買う手法をバックテストをしてみました。

日本株では順張り手法のバックテスト結果が一般的には良くありませんが、

年初来高値更新は書籍やネットで良く語られるので結果を確認してみます。

 

【仕掛け条件】

年初来高値を更新したら買い。

 

【手仕舞い条件】

購入して20日(営業日)後に売る。

 

【検証期間】

2000/1/4~2020/5/21

 

【結果】

取引回数 54356回
勝率 50.39%
期待値 1.51%

 

思っていたより勝率/期待値が高いです。

 

高くなってから買う系の手法は一般的に勝率が低くなるんですが、これは50%を超えています。

 

また、別パターンとしてよく語られる、

年初来高値更新、かつ、出来高急増(※)した銘柄を買う手法についても調べました。
※今回は前日比50%以上増に設定。
 
【結果(出来高急増パターン)】

取引回数 30411回
勝率 50.52%
期待値 1.74%

若干パフォーマンスが改善しました。結構よさげな手法だと思います。

久しぶりに投稿します。

最近はリモートワークにも慣れてきてシストレのための時間が作れるようになりました。

 

そんな中、以前から欲しいと思っていた日本株のバックテストツールのイザナミを購入しました。

お値段 16万5000円だったので、支払った分以上はしっかりと活用していきたいと思います!

 

使ってみた感想としては、

操作画面がシステム寄り(プログラミングに近い)なので普段から論理式(IF/OR/AND等)に

慣れていないと多少時間がかかるかもしれませんが、

プログラミングをやっている人にとってはかなり使いやすい(かつフレキシブルな)ツールだと思います。

 

そして何より検証が早い!

5000銘柄×15年分の検証が1分ほどで終わります。

 

自分も金融系のSEをしていて過去にはバックテストツールを作ったこともありますが、

スピードは(当然ながら)比較になりません。いろんな工夫をされているんだと思います。

 
==============
で、早速、最近気になっていたことを調査しました。結果を公開します。
 
【調査事項】
金曜終値買い→月曜寄付き売りはどんなパフォーマンスになるのか。
 
【調査目的】
週末持越しの影響を調べる
 
【対象銘柄】
売買代金が十分にある銘柄(5日連続で1億円以上)
 
【イザナミ設定画面】
 
※売買代金の[100]は[100]×100万円=1億円の意味。
※曜日の[5]は金曜。(月曜:1~金曜:5)
 
【結果】
総取引回数 436592回
勝率 58.46%
期待値 0.08%
 
【所感】
勝率に関しては十分な取引回数があっての58%なので、ある程度の傾向が出ているといえますが、
期待値がほぼプラマイゼロ(0.08%)では投資戦略としては使えませんね(-_-;)
 
おそらく、ほとんどの銘柄には金曜買い→月曜売りは有効な戦略です。
但し、一部の銘柄で週末に悪材料が出て大きく下がるため、
合計すると期待値がほぼプラマイゼロ付近になってしまうんだと思います。
 
有効な数値が得られず残念。。
 
今後も色々検証して、報告していきたいと思います。

先日、バックテストでデイトレの良さげな手法を見つけたので、

自動売買で実践しようと思いましたが狙ったタイミングで売買ができず失敗しました。

 

デイトレの自動売買は難しい!!

 

成行買いは思わぬ高値で買ってしまう可能性があるため使いづらいし、

指値注文は板が厚かったり値動きが悪いと約定せずにタイミングを逃します。

バックテストの手法を再現することが非常に難しかったです。


なので、デイトレの自動売買はやめようと思います。

Twitterでは億トレも見かけるので、不可能ではないと思うんですが、

ツイートを見ているとかなりの努力をされていて真似はできないな、と。

 

スイングトレードは引き続き模索しようと思います。

やはり、今の証券会社の手数料無料の流れはシストレに有利だと思うので。

(優位性のある手法が見つかれば無料の範囲内で試せるため)

 

スイングトレードであれば以下の買い方をすれば、

決まったタイミングで安定的に買うことができると考えています。

 

①大引けの「引成」で購入する。

②売買代金が大きい銘柄に限定する(1億円以上)。
③自分の注文が売買代金の0.1%程度以下になるようにする。

 

①はバックテストと状況を合わせるためです。

バックテストは「終値」で買う前提で行い、実践時には「引成」で買えば状況は一致します。

 

②③は自分の注文で大きく株価が動いてしまうのを防ぐ目的です。

自分の影響が大きいとその後の値動きに影響を与えてしまい、

バックテストの結果が再現しなくなる可能性が高まります。

また、ファンダメンタル的にも割高になって翌日以降売られるリスクがあります。

今日は超シンプルな検証を行いました。

検証したのは「当日株価がXX%上昇(下落)した時にその後の株価がどうなっているか」です。

 

調査目的は、当日株価がどのくらい変動した日に株を買えば良いか明確にすることです。

 

大幅上昇/小幅上昇/大幅下落/小幅下落のどのタイミングで買えばよいのか、
傾向が見えればよいと思い検証しました。
 
【バックテスト対象】
期間:2005/1/1~2020/3/18
銘柄:全4095 銘柄(ETF含む)
 
【検証方法】
20日(営業日)ごとに全銘柄を購入し20日後に売却した場合の勝率/利益率を
購入した日の株価変動率ごとに集計(-10%~+10%まで1%刻み)。

 

【結果】
以下の結果になりました。
 
【感想】
正直、全体としての明確な傾向は見られません。
なんとなくは、大幅下落⇒大幅上昇⇒小幅上昇⇒小幅下落の順に良さそうです。
 
唯一、明確に傾向が出ているのは、
変動率が「-10%~-6%」の場合に勝率/利益率が高くなることでしょうか。
当日の大幅下落は買いのチャンスかもしれません。
 
但し、「-10%~-6%」の銘柄でも、業績の下方修正や減配などが原因の場合は、
その後の自律反発は期待できないケースが多いと思います。
(正当な下落理由があり、それを織り込んだだけと考えられるため)
 
それ以外の理由(配当落ち、優待権利落ち、信用規制、業績に影響の少ないBADニュース等)で、
「-10%~-6%」になった銘柄は買いのチャンスかもしれません。
 
また、当日株価が-10%以下になった銘柄は無視しています。
そういう銘柄は連続ストップ安や、最悪、そのまま0円(上場廃止)に向かう事もあり得るため、
手を出すべきではないと考えているためです。

楽天RSSを使った東証とPTSの価格差を見つけるプログラムを公開します。

 

最初に書いておきますが、実際に動かしてみた結果、

本プログラムを使って儲けるチャンスはほとんどありません(;'∀')

以下のサンプルをベースに儲かるアイデアがある方、こっそり教えてください(笑)。

 

目的は東証とPTS市場(※1)で同一銘柄の価格(※2)をチェックして、
東証で買ってPTSで売れば儲かる(もしくはその逆の)タイミングを監視することです。

※1 ジャパンネクスト証券、 チャイエックス・ジャパンの2市場

※2 通常は同一銘柄の株価は同じになるがタイミングによって若干の価格差が生まれる。

 
このプログラムを使って一時期ビットコイン等で流行った裁定取引(アービトラージ)を
してみようと考えました。

 

この裁定取引ですが、単純に「東証よりPTSの方が安く買える」銘柄を探しても意味がありません。

通常、買気配<売気配となっている気配値の逆転現象を探す必要があります。

 

つまり、以下のような状態を見つけても意味がありません。

 (東証売り気配)100円 (東証買い気配) 97円

 (PTS売り気配) 98円  (PTS買い気配) 97円

 

この場合、東証(100円)よりもPTS(98円)で安く買えるのは事実なんですが、

買い気配が97円なので、PTSで安く(98円で)買ってもそれより高く売れません。

(余談ですが通常、株を買うときは東証とPTSのより安い方を自動で買ってくれるので、

 上記の「PTSが安い」という情報にはあまり価値もありません。)

 

このプログラムでは、以下のような状態を探します。

 (東証売り気配)100円 (東証買い気配) 97円

 (PTS売り気配) 96円  (PTS買い気配) 95円

 
この場合、売気配と買気配が逆転しているので、
PTSで96円買いして、すぐに東証で97円で売れます。
 
但し、このような逆転現象は1日に数回見かける程度です。
しかも、見つけた後すぐに解消されるため、
見つけた後に超高速で売買するシステムを作る必要があります。
システム作成にかなりの工数かかりそうですが、リターンは1日数百円のレベルだと思います。
やる価値は無いと思います( ;∀;)
 
そんなプログラムですが、以下がサンプルになります。
 
【前提条件】
・VisualStudioで新規プロジェクト(C#/コンソールアプリケーション)を作成していること
・VisualStudioのNuGetで「NDde」を検索しインストールしていること
・楽天証券のツール「MarketSpeed」を起動してログインしていること
・楽天証券のツール「楽天RSS」を起動していること
 
【サンプルコード】
static void Main(string[] args)
{
    //銘柄コードを指定
    List<string> list = new List<string>();
    list.Add("9984"); //ソフトバンク
    list.Add("9983"); //ファーストリテイリング
    list.Add("7974"); //任天堂
    list.Add("8306"); //三菱UFJ
    list.Add("8035"); //東京エレクトロン
    list.Add("6758"); //ソニー

    //無限ループ
    while (true)
    {
        //銘柄毎に繰り返し
        foreach (var ticker in list)
        {
            //5秒待機
            Thread.Sleep(5000);

            //初期化
            string sName = "";
            double bidTmp = 9999999;
            double bidT = 9999999;
            double bidJ = 9999999;
            double bidC = 9999999;
            double ascTmp = 0;
            double ascT = 0;
            double ascJ = 0;
            double ascC = 0;

            //3環境で繰り返し(東証/JNX/CHX)
            for (int ii = 1; ii <= 3; ii++)
            {
                //銘柄名に取引所コードを付ける(例えば"9984.JNX"はジャパンネクストのソフトバンク)
                string tickerTmp = "";
                if (ii == 1)
                    tickerTmp = ticker + ".T";
                else if (ii == 2)
                    tickerTmp = ticker + ".JNX";
                else if (ii == 3)
                    tickerTmp = ticker + ".CHJ";

                try
                {
                    using (NDde.Client.DdeClient client = new NDde.Client.DdeClient("RSS", tickerTmp))
                    {
                        //RSSに接続
                        client.Connect();

                        //銘柄名を取得
                        if (ii == 1)
                        {
                            byte[] data0 = client.Request(@"銘柄名称", 1, 1000);
                            string str0 = Encoding.Default.GetString(data0).Replace("\0", "");
                            sName = str0.Trim();
                        }
                        //売り気配値を取得
                        byte[] data1 = client.Request(@"最良売気配値", 1, 1000);
                        string str1 = Encoding.Default.GetString(data1).Replace("\0", "");
                        //買い気配値を取得
                        byte[] data2 = client.Request(@"最良買気配値", 1, 1000);
                        string str2 = Encoding.Default.GetString(data2).Replace("\0", "");
                        //気配値を数値変換
                        bidTmp = double.Parse(str1.Trim());
                        ascTmp = double.Parse(str2.Trim());
                    }
                }
                catch (Exception ex)
                {
                }

                //気配値を変数に保持
                if (ii == 1)
                {
                    //東証の気配値
                    bidT = bidTmp;
                    ascT = ascTmp;
                }
                else if (ii == 2)
                {
                    //JNXの気配値
                    bidJ = bidTmp;
                    ascJ = ascTmp;
                }
                else if (ii == 3)
                {
                    //CHJ
                    bidC = bidTmp;
                    ascC = ascTmp;
                }
            }

            //出力する
            string output = "***********************************************" + Environment.NewLine;
            output = output + "銘柄コード:" + ticker + " 銘柄名:" + sName + Environment.NewLine;
            output = output + "----------------" + Environment.NewLine;
            output = output + "東証" + Environment.NewLine;
            output = output + "売気配:" + bidT + Environment.NewLine;
            output = output + "買気配:" + ascT + Environment.NewLine;
            output = output + "----------------" + Environment.NewLine;
            output = output + "ジャパンネクスト" + Environment.NewLine;
            output = output + "売気配:" + bidJ + Environment.NewLine;
            output = output + "買気配:" + ascJ + Environment.NewLine;
            output = output + "----------------" + Environment.NewLine;
            output = output + "チャイエックス" + Environment.NewLine;
            output = output + "売気配:" + bidC + Environment.NewLine;
            output = output + "買気配:" + ascC + Environment.NewLine;
            output = output + "----------------" + Environment.NewLine;
            output = output + "***********************************************" + Environment.NewLine;
            Console.WriteLine(output);
 
            //東証の売り気配が安い場合
            if (bidT < ascJ)
            {
                output = "";
                output = output + "☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆" + Environment.NewLine;
                output = output + "東証が安い(対ジャパンネクスト)" + Environment.NewLine;
                output = output + "☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆" + Environment.NewLine;
                Console.WriteLine(output);
            }
            if (bidT < ascC)
            {
                output = "";
                output = output + "☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆" + Environment.NewLine;
                output = output + "東証が安い(対チャイエックス)" + Environment.NewLine;
                output = output + "☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆" + Environment.NewLine;
                Console.WriteLine(output);
            }
            //JNXの売り気配が安い場合
            if (bidJ < ascT)
            {
                output = "";
                output = output + "☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆" + Environment.NewLine;
                output = output + "ジャパンネクストが安い(対東証)" + Environment.NewLine;
                output = output + "☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆" + Environment.NewLine;
                Console.WriteLine(output);
            }
            if (bidJ < ascC)
            {
                output = "";
                output = output + "☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆" + Environment.NewLine;
                output = output + "ジャパンネクストが安い(対チャイエックス)" + Environment.NewLine;
                output = output + "☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆" + Environment.NewLine;
                Console.WriteLine(output);
            }
            //CHXの売り気配が安い場合
            if (bidC < ascT)
            {
                output = "";
                output = output + "☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆" + Environment.NewLine;
                output = output + "チャイエックスが安い(対東証)" + Environment.NewLine;
                output = output + "☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆" + Environment.NewLine;
                Console.WriteLine(output);
            }
            if (bidC < ascJ)
            {
                output = "";
                output = output + "☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆" + Environment.NewLine;
                output = output + "チャイエックスが安い(対ジャパンネクスト)" + Environment.NewLine;
                output = output + "☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆" + Environment.NewLine;
                Console.WriteLine(output);
            }
        }
    }
}

 

【実行結果】

 

東証とPTSの売気配、買気配をコンソールに出力します。

東証とPTSの気配が逆転している場合は☆マークで囲って、

どの市場がどの市場に対して安いかを出力します。

先日SBIの口座を見ていたら、以前開設したはずのNISA枠が0円になっていることに気づきました。

よく見ると2017年の時点でマイナンバーの登録が必要だったんですね。

 

なので、NISA枠を再申請し、現状は開設待ちなんですが、

NISA枠で買っておいて放置するための銘柄を検索してみました。


とりあえず、4~5年の長期で持つことを前提に以下の条件で、

「株マップ.COM」の簡易スクリーニングで検索してみました。

 

【検索条件】

①今後続くであろうコロナ不況に耐えれる、現金/自己資本がたっぷりある会社。

 ⇒PBR 0.5以下、自己資本比率 40%以上

 
②割安で放置されており、いつかは価格修正が入ると期待できる銘柄。

 ⇒PER 10倍以下、配当利回り 3%以上

 

③ある程度売買がある銘柄(いつまでも割安放置されそうな地味銘柄を避ける)。

 ⇒売買代金 5000万円以上

 

【結果】

 

この条件だと35銘柄が表示されました。低PBR順に並べるとこんな感じです。

 

7261 マツダがかなりお安いように見えますが、どうなんでしょうね?

割安に放置される理由があるんでしょうか?

 

4331、5851、4676あたりもよさそうに見えます。
放置しておけばコロナ不況後に価格修正が期待できるんではないでしょうか。
 
この辺の銘柄を早速今月から給料の1/3か半分くらいずつ買って、
ゆっくりNISA枠に突っ込んでいこうと思います。
 
利益を急がずにリスク分散をしてゆっくり投資できるのは、
兼業投資家の強みですね!

 

では。

 

本ブログは株式投資/シストレがメインなので本題ではないですが、

DTM(SONAR)を使ってフジファブリックの赤黄色の金木犀をコピーしてみました。

 

ギターのみ別売りプラグインのREAL STRATを使用し、

その他の音源はSONAR付属のものです。

 

 

在宅勤務でここ数週間、家に引きこもり中の者です。
一人暮らしが長いからか全くストレスを感じることはなく気楽にやってます。
(婚期が遠のきそうですが)
 

タイトルにあるプログラムですが、
松井証券のホームページにログインして一日信用の売買注文を出すプログラムを

作成しましたので公開します。
 
以下、注意点等です。
・サンプルでは一日信用で自動売買をしています。
 但し、発注するまでに10~20秒かかるため、裁定取引(アービトラージ)や
 スキャルピングといった高速の取引が必要となる用途には使えません。

 

・ログインID、ログインパスワード、取引パスワードはダミーの文字列が入っています。

 実際のID/パスワードに置き換えてください。
 
・サンプルではトヨタ自動車(7203)で、
 新規買い/買いの精算/新規売り/売りの精算の指値注文、成行注文をしています。
 但し、新規買いの成行注文以外はコメントアウトしています。
 
・発注ボタンを押下する部分はコメントアウトしています。
 発注を行う場合は「☆」で囲ってある部分のコメントアウトを外してください。
 
以下サンプルです。

 

'*****************ログイン情報*****************
Public Const C_LOGIN_ID = "XXXXXXXX"    'ログインID
Public Const C_LOGIN_PASS = "XXXXXXXX"  'ログインパスワード
Public Const C_TRADE_PASS = "XXXXXXXX"  '取引パスワード
'**********************************************

'グローバル変数
Public G_objIE
'定数
Public Const C_URL_LOGIN = "https://www.deal.matsui.co.jp/ITS/login/"
Public Const C_ORDER_TYPE_NEWBUY = 1
Public Const C_ORDER_TYPE_REPBUY = 2
Public Const C_ORDER_TYPE_NEWSELL = 3
Public Const C_ORDER_TYPE_REPSELL = 4

'メイン関数
Sub Main()

    '松井証券のウェブサイトにログイン
    Dim blnResult As Boolean
    blnResult = MatsuiLogin()
    
    'ログインに失敗した場合
    If blnResult = False Then
        MsgBox "ログイン失敗!!"
        Exit Sub
    End If
    
    'トヨタ自動車(7203)を新規買いする場合
    '100株、6000円で指値注文
    'Call NewOrder("7203", C_ORDER_TYPE_NEWBUY, "100", "6000")
    '100株、成行注文
    Call NewOrder("7203", C_ORDER_TYPE_NEWBUY, "100", "成行")

    '買いポジションを精算する場合
    '100株、6000円で指値注文
    'Call NewOrder("7203", C_ORDER_TYPE_REPBUY, "100", "6000")
    '100株、成行注文
    'Call NewOrder("7203", C_ORDER_TYPE_REPBUY, "100", "成行")

    'トヨタ自動車(7203)を新規売りする場合
    '100株、6000円で指値注文
    'Call NewOrder("7203", C_ORDER_TYPE_NEWSELL, "100", "6000")
    '100株、成行注文
    'Call NewOrder("7203", C_ORDER_TYPE_NEWSELL, "100", "成行")

    '売りポジションを精算する場合
    '100株、6000円で指値注文
    'Call NewOrder("7203", C_ORDER_TYPE_REPSELL, "100", "6000")
    '100株、成行注文
    'Call NewOrder("7203", C_ORDER_TYPE_REPSELL, "100", "成行")

End Sub


'松井証券にログインして一日信用画面に移動する
Function MatsuiLogin() As Boolean
    
    MatsuiLogin = False
    
    'IEを起動する
    Set G_objIE = CreateObject("Internetexplorer.Application")
    G_objIE.Visible = True
    
    'ログイン画面を開く
    G_objIE.Navigate C_URL_LOGIN
    
    '画面更新を待つ(5秒)
    Application.Wait Now() + TimeValue("00:00:05")
    
    'IEのステータスがBusy以外になるのを待つ
    WaitWebStatus
    
    '簡単注文機能「使用する」を検索して押す
    Dim elem As Object
    For Each elem In G_objIE.document.getElementsByTagName("input")
        If elem.Name = "easyTradeFlg" And elem.Type = "radio" And elem.Value = "1" Then
            elem.Click
        End If
    Next
    
    '画面更新を待つ
    Application.Wait Now() + TimeValue("00:00:03")
    WaitWebStatus
    
    'ユーザ/パスワードのテキストボックスを検索して入力する
    For Each elem In G_objIE.document.getElementsByTagName("input")
        'ユーザ入力
        If elem.Name = "clientCD" Then
            elem.Value = C_LOGIN_ID
        End If
        
        'パスワード入力
        If elem.Name = "passwd" Then
            elem.Value = C_LOGIN_PASS
        End If
    Next
    
    'ログインボタンを押す
    Dim elemButton As HTMLInputElement
    Set elemButton = G_objIE.document.getElementById("btn_opn_login")
    elemButton.Click
    Set elemButton = Nothing
    
    '画面更新を待つ
    Application.Wait Now() + TimeValue("00:00:05")
    WaitWebStatus
    
    '取引パスワードを入力
    For Each elem In G_objIE.document.getElementsByTagName("input")
        If elem.Name = "pinNo" Then
            elem.Value = C_TRADE_PASS
        End If
    Next
    
    '画面更新を待つ
    Application.Wait Now() + TimeValue("00:00:03")
    WaitWebStatus
    
    '次へボタンを押す
    For Each elem In G_objIE.document.getElementsByTagName("input")
        If elem.alt = "次へ" Then
            elem.Click
        End If
    Next
    
    '画面更新を待つ
    Application.Wait Now() + TimeValue("00:00:03")
    WaitWebStatus
    
    'ウェブページのドキュメント取得
    Dim objDoc As HTMLDocument
    Set objDoc = G_objIE.document
    
    '上部メニューのフレーム取得
    Set objFrame = objDoc.frames("GM")
    Set dc = objFrame.document
    
    '上部メニューに「一日信用」が存在すればログイン成功と判定する
    Dim elemTmp
    On Error Resume Next
    For Each elemTmp In dc.getElementsByTagName("b")
        If elemTmp.outerText = "一日信用" Then
            'ログイン成功フラグ
            MatsuiLogin = True
            Exit For
        End If
    Next
    On Error GoTo 0

    Set elemButton = Nothing
    Set objDoc = Nothing
    Set objFrame = Nothing
    Set dc = Nothing

End Function

'新規注文を出す
Sub NewOrder(strCode As String, intType As Integer, strStockCount As String, strPrice As String)
    
    'ウェブページのドキュメント取得
    Dim objDoc As HTMLDocument
    Set objDoc = G_objIE.document
    
    '上部メニューのフレーム取得
    Set objFrame = objDoc.frames("GM")
    Set dc = objFrame.document
    
    '上部メニューから一日信用を検索して押す
    Dim elemTmp
    On Error Resume Next
    For Each elemTmp In dc.getElementsByTagName("b")
        If elemTmp.outerText = "一日信用" Then
            elemTmp.Click
            Exit For
        End If
    Next
    On Error GoTo 0
    
    '画面更新を待つ
    Application.Wait Now() + TimeValue("00:00:03")
    WaitWebStatus
    
    '左メニューのフレーム取得
    Set objFrame = objDoc.frames("LM")
    Set dc = objFrame.document
    
    '左メニューから銘柄テキストボックスを探し銘柄コードを入力
    On Error Resume Next
    For Each elemTmp In dc.getElementsByTagName("input")
        If elemTmp.Name = "prmDscr" Then
            elemTmp.Value = strCode
            Exit For
        End If
    Next
    On Error GoTo 0
    
    '画面更新を待つ
    Application.Wait Now() + TimeValue("00:00:01")
    WaitWebStatus
    
    '銘柄検索ボタンを押す
    On Error Resume Next
    For Each elemTmp In dc.getElementsByTagName("input")
        If elemTmp.Type = "submit" And elemTmp.Value = "銘柄検索" Then
            elemTmp.Click
            Exit For
        End If
    Next
    On Error GoTo 0
    
    '画面更新を待つ
    Application.Wait Now() + TimeValue("00:00:03")
    WaitWebStatus
    
    '表示内容を取得取得
    Set objFrame = objDoc.frames("CT")
    Set dc = objFrame.document
    
    'ラジオボタンを押す
    If intType = C_ORDER_TYPE_NEWBUY Then
        On Error Resume Next
        For Each elemTmp In dc.getElementsByTagName("input")
            If elemTmp.Type = "radio" And elemTmp.ID = "tradeKbn_723" Then
                elemTmp.Click
                Exit For
            End If
        Next
        On Error GoTo 0
    ElseIf intType = C_ORDER_TYPE_REPBUY Then
        On Error Resume Next
        For Each elemTmp In dc.getElementsByTagName("input")
            If elemTmp.Type = "radio" And elemTmp.ID = "tradeKbn_731" Then
                elemTmp.Click
                Exit For
            End If
        Next
        On Error GoTo 0
    ElseIf intType = C_ORDER_TYPE_NEWSELL Then
        On Error Resume Next
        For Each elemTmp In dc.getElementsByTagName("input")
            If elemTmp.Type = "radio" And elemTmp.ID = "tradeKbn_721" Then
                elemTmp.Click
                Exit For
            End If
        Next
        On Error GoTo 0
    ElseIf intType = C_ORDER_TYPE_REPSELL Then
        On Error Resume Next
        For Each elemTmp In dc.getElementsByTagName("input")
            If elemTmp.Type = "radio" And elemTmp.ID = "tradeKbn_733" Then
                elemTmp.Click
                Exit For
            End If
        Next
        On Error GoTo 0
    End If
    
    '画面更新を待つ
    Application.Wait Now() + TimeValue("00:00:03")
    WaitWebStatus
    
    '株数を入力する
    On Error Resume Next
    For Each elemTmp In dc.getElementsByTagName("input")
        If elemTmp.Name = "orderNominal" Then
            elemTmp.Value = strStockCount
            Exit For
        End If
    Next
    On Error GoTo 0
    
    '画面更新を待つ
    WaitWebStatus

    '成行注文
    If strPrice = "成行" Then
        On Error Resume Next
        For Each elemTmp In dc.getElementsByTagName("input")
            If elemTmp.Name = "orderNari" Then
                elemTmp.Click
                Exit For
            End If
        Next
        On Error GoTo 0
    '指値注文
    Else
        On Error Resume Next
        For Each elemTmp In dc.getElementsByTagName("input")
            If elemTmp.Name = "orderPrc" Then
                elemTmp.Value = strPrice
                Exit For
            End If
        Next
        On Error GoTo 0
    End If
    
    '画面更新を待つ
    Application.Wait Now() + TimeValue("00:00:03")
    WaitWebStatus

    '注文確認ボタンを押す
    On Error Resume Next
    For Each elemTmp In dc.getElementsByTagName("input")
        If elemTmp.alt = "注文確認" And elemTmp.Name = "tyukakuButton" Then
            elemTmp.Click
            Exit For
        End If
    Next
    On Error GoTo 0
    
    '画面更新を待つ
    Application.Wait Now() + TimeValue("00:00:05")
    WaitWebStatus

    '表示内容を取得取得
    Set objFrame = objDoc.frames("CT")
    Set dc = objFrame.document

'☆☆☆ここのコメントアウトを外すと実際に注文ボタンが押下されます☆☆☆
'
'    '注文するボタンを押す
'    On Error Resume Next
'    For Each elemTmp In dc.getElementsByTagName("input")
'        If elemTmp.alt = "注文する" Then
'            elemTmp.Click
'            Exit For
'        End If
'    Next
'    On Error GoTo 0
'
'☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
    
    '画面更新を待つ
    Application.Wait Now() + TimeValue("00:00:03")
    WaitWebStatus

    Set objDoc = Nothing
    Set objFrame = Nothing
    Set dc = Nothing

End Sub

'WebサイトのBusyが解消されるまで待つ
Function WaitWebStatus()
    Do While G_objIE.readyState <> 4
        Do While G_objIE.Busy = True
        Loop
    Loop
End Function

 

 
※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
プログラムはご自身の判断、責任にてご使用下さい。
※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※

久しぶりの記事になります。

以前から投資するタイミングを決める際に重視している「25日移動平均乖離率」について、

本当に重視すべき指標なのかが気になったのでバックテストをしてみました。

 

【バックテスト対象】
期間:2005/1/1~2020/3/18
銘柄:全4095 銘柄(ETF含む)
 
【検証方法】
20日(営業日)ごとに全銘柄を購入し20日後に売却した場合の勝率/利益率を
購入時の25日移動平均乖離率ごと(10%刻み)に集計。

 

【結果】
以下の結果になりました。
 
【感想】
乖離率が「-20%」を超えると勝率/利益率ともに非常に高くなる結果となり、
乖離率が「-20%」を超える銘柄は買いのチャンスと考えてよいと思います。

 

【注記】
今回のバックテスト期間(2005/1/1~2020/3/18)では相場全体が50%以上上昇しています。
また、バックテストの期間中に上場廃止になった銘柄はテストしていません。
そのため、相場全体の上昇分や生存者バイアスによって勝率/利益率が底上げされています。
今後も相場全体が上昇するとは限らないので、勝率や利益率は参考程度に見て、
「乖離率ごとの投資結果の差異」を見るためのテストとして見てください。