English Русский 中文 Español Deutsch Português
EAステータス SMS 通知機能

EAステータス SMS 通知機能

MetaTrader 4 | 4 11月 2015, 10:05
762 0
Дмитрий
Дмитрий

はじめに

私の仕事はよく断続的にターミナルをモニターするサガのため中断されます。それはほんの20~30分であるかもしれませんし丸1日であるかもしれません。そのため私は、詳細な情報、ブレイクアウトから私のコンピューターが週末明けにスリープモードから起動しないような問題までを知らせるSMSを送るシステムを開発しようと決めました。本稿で紹介するシステムは多くのトレーダーに有用で、また十分に満足した方法を見つけらず自分自身の「マスターピース」を作りたいと願うトレーダーに奉仕するものでしょう。

本稿では、特定のタスクのワーキングソリューション開発をおこなっていきます。私は特段Java開発のプロ並みのスキルを持っているわけではありませんので、Java開発者である私の仕事仲間にお願いしてデバックやミスコードを直してもらわなければなりませんでした。

目次

  1. グーグルカレンダーの特徴
  2. グーグルデータAPIのインストールについて
  3. システムフローチャート
  4. Javaアプリケーションコード
  5. .batファイルコード
  6. エキスパートアドバイザーコード
  7. 短所
  8. まとめ

グーグルカレンダーの特徴

SMS通知システムの開発において、私はグーグルカレンダーを使うことに決めて、イベントを無料カレンダー内に設定し、イベントの通知手段としてSMSを利用できるようにしました。この特定の目的のためにグーグルの特別なセパレートファイルを作成しました。

簡潔に言うと、運用規則の詳細は以下のとおりです。:現在のメッセージが午前9時59分(上のスクリーンショットをみてください)までに削除されない、つまり、もしターミナルが現在のメッセージを別のメッセージに置き換えるためにグーグルサーバ―に接続しないならば、SMSが適した通知をあなたの携帯に送るでしょう。

グーグルデータAPIのインストールについて

ソフトウェアソリューションの開発におけるグーグルのサービスを使うことができるように、グーグルはGoogle Data APIsの資料を提供しています。
Java開発者がグーグルカレンダーを使って作る際に必要な全ての資料はこのリンクGoogle Calendar APIs and Toolsを利用して見つけることができます。

プログラミングを開始するために、Google Data Java Client Libraryをインストールする必要がりあす。同じページにEclipseのライブラリに関連する資料のリンクを見つけることができます。これが私が使用したもので、これをお勧めします。: Using Eclipse with Google Data APIs.

システムフローチャート

フローチャートにいく前に最初にコメントすべきでしょう。:

  • StopTXTイベントは念のため手動遠隔操作でSMSのフローを中止することができることを要求します。;
  • ReanimationTXTイベントはある理由でターミナルが対応する警告SMSが送られた に接続するようになることを要求します。;


Javaアプリケーションコード

全てのソースコードと使用した入れるは本稿の最後に添付しています。

package Calendar;
/* 留意事項:これはコマンドラインアプリケーションです。 
    このテンプレートを以下の引数と一緒に実行してください。:

                arg[0] = username
                arg[1] = password
*/

import com.google.gdata.client.GoogleService;
import com.google.gdata.client.Query;
import com.google.gdata.client.calendar.CalendarService;
import com.google.gdata.data.DateTime;
import com.google.gdata.data.PlainTextConstruct;
import com.google.gdata.data.calendar.CalendarEntry;
import com.google.gdata.data.calendar.CalendarEventEntry;
import com.google.gdata.data.calendar.CalendarEventFeed;
import com.google.gdata.data.calendar.CalendarFeed;
import com.google.gdata.data.extensions.Reminder;
import com.google.gdata.data.extensions.When;
import com.google.gdata.data.extensions.Reminder.Method;
import com.google.gdata.util.AuthenticationException;
import com.google.gdata.util.ServiceException;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

public class Calendar {

    public static void main(String[] args) {

        try {
            //--- 外部変数 ----------------------------
            String alertTxt = args[2];
            String reanimationTxt = args[3];
            String stopSMS = args[4];
            int timePeriod = Integer.parseInt(args[5]); //ターミナルが接続される 
                                                        //インターバル間隔(分)
            int mode = Integer.parseInt(args[6]);
            int startHour = Integer.parseInt(args[7]);
            int startMin = Integer.parseInt(args[8]);
            //---------------------------------------------------
            //--- 内部変数 --------------------------
            URL feedUrl = new URL("http://www.google.com/calendar/feeds/default/private/full");
            //イベント実行のためのリンク
            URL calendarUrl = new URL("http://www.google.com/calendar/feeds/default/allcalendars/full");
            //カレンダー実行のためのリンク    
            //---------------------------------------------------
            System.out.println(">>----------  Start   ----------<<");

            //新しいカレンダーサビスの作成、グーグルに接続
            CalendarService myService = new CalendarService("My Application");
            myService.setUserCredentials(args[0], args[1]);    //引数としてのログインとパスワード

            //イベント検索のための変数を宣言
            Query myQuery = new Query(feedUrl);
            CalendarEventFeed myResultsFeed;
            CalendarEventEntry firstMatchEntry = null;
            String myEntryTitle;
            URL deleteUrl;
            When timeVar;
            SimpleDateFormat formater = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
            Date newDate = new Date();
            CalendarEventEntry myEntry;
            When eventTimes = new When();
            DateTime startTime = null;
            DateTime endTime = null;
            int reminderMinutes;
            Method methodType = Method.SMS;
            Reminder reminder = new Reminder();
            CalendarEventEntry insertedEntry;

            //クゥエリ検索の準備
            myQuery.setFullTextQuery(stopSMS);            // stopSMS テキストイベント
            myResultsFeed = myService.query(myQuery, CalendarEventFeed.class);
            if (myResultsFeed.getEntries().size() > 0) {
                System.out.println(">> STOP event found. \n>> Finish");
                return;
            }

            //クゥエリ検索の準備 
            myQuery.setFullTextQuery(reanimationTxt);    // reanimationTxt テキストイベント
            myResultsFeed = myService.query(myQuery, CalendarEventFeed.class);
            if (myResultsFeed.getEntries().size() > 0) {    //見つかった場合
                System.out.println(">> REANIMATION event found");
                //最初に合致したエントリーのタイトルを取得
                firstMatchEntry = (CalendarEventEntry) myResultsFeed.getEntries().get(0);
                myEntryTitle = firstMatchEntry.getTitle().getPlainText();

                //reanimationTxtイベントが見つかったら削除
                deleteUrl = new URL(firstMatchEntry.getEditLink().getHref());
                myService.getRequestFactory().setHeader("If-Match", "*");
                myService.delete(deleteUrl);
                System.out.println(">> ...deleting REANIMATION event");
            }

            //クゥエリ検索の準備
            myQuery.setFullTextQuery(alertTxt);            // alertTxt テキストイベント
            myResultsFeed = myService.query(myQuery, CalendarEventFeed.class);
            if (myResultsFeed.getEntries().size() > 0) {    //見つかった場合
                System.out.println(">>  >> ALERT event found");
                //最初に合致したエントリーのタイトルを取得
                firstMatchEntry = (CalendarEventEntry) myResultsFeed.getEntries().get(0);
                myEntryTitle = firstMatchEntry.getTitle().getPlainText();

                timeVar = firstMatchEntry.getTimes().get(0);
                System.out.println(">>  >> event start&stop time         : " 
                        + timeVar.getStartTime() + "\n>>        >>                               : " 
                        + timeVar.getEndTime());
                System.out.println(">>  >> event start     (milliseconds): " 
                        + timeVar.getStartTime().getValue());
                System.out.println(">>  >> new event start (milliseconds): " 
                        + (newDate.getTime() - (1000 * 60 * timePeriod)));

                if (timeVar.getStartTime().getValue() > newDate.getTime() - (1000 * 60 * 0)) {    
                    //過去イベントのスタートタイムがtimePeriod(分)前より小さいならば
                    //削除
                    deleteUrl = new URL(firstMatchEntry.getEditLink().getHref());
                    myService.getRequestFactory().setHeader("If-Match", "*");
                    myService.delete(deleteUrl);
                    System.out.println(">>              >> event start > new event start");
                    System.out.println(">>              >> ...deleting event");
                    System.out.println(">>              >>    #M###      ##M    #M#  ");
                    System.out.println(">>              >>   ########    ###   ###   ");
                    System.out.println(">>              >>   ###  ###    ###  ###    ");
                    System.out.println(">>              >>  ###    ###   ### ###     ");
                    System.out.println(">>              >>  M##    ###   ######M     ");
                    System.out.println(">>              >>  ###    ###   #### ###    ");
                    System.out.println(">>              >>  ###    ###   ###  ###    ");
                    System.out.println(">>              >>  ###    ###   #M#   ###   ");
                    System.out.println(">>              >>   ###  ###    ###   ###   ");
                    System.out.println(">>              >>   ########    ###    ###  ");
                    System.out.println(">>              >>     ####      ###     ### ");
                } else {    //タイムがtimePeriodより前の場合、SMSは既に送られたことを意味します。
                    //削除
                    deleteUrl = new URL(firstMatchEntry.getEditLink().getHref());
                    myService.getRequestFactory().setHeader("If-Match", "*");
                    myService.delete(deleteUrl);
                    System.out.println(">>              >> SMS has gone already");
                    System.out.println(">>              >> event start < new event start");
                    System.out.println(">>              >> ...deleting event");
                    System.out.println(">>              >>   .M####   M##M   ###M   .#####   ");
                    System.out.println(">>              >>  ########  ####   ####  ########  ");
                    System.out.println(">>              >>  ###  ###  ####   ####  #M#  ###  ");
                    System.out.println(">>              >>  ###       ###M# #####  ###       ");
                    System.out.println(">>              >>  #M####    ##### #####  ######    ");
                    System.out.println(">>              >>   ######   ### # # @##   #M####   ");
                    System.out.println(">>              >>     #####  ### # # ###     #####  ");
                    System.out.println(">>              >>  #M#  ###  ### # # ###  M##  ###  ");
                    System.out.println(">>              >>  ###  ###  ### ### ###  ###  ###  ");
                    System.out.println(">>              >>   ######   ### ### ###   ######   ");
                    System.out.println(">>              >>    ####    ###  #  ###    ####    ");
                    //新イベント作成
                    myEntry = new CalendarEventEntry();
                    myEntry.setTitle(new PlainTextConstruct(reanimationTxt));  //タイトル設定E

                    newDate.setTime(newDate.getTime() + 1000 * 60 * 1); //現在の時間 + 1分
                    startTime = DateTime.parseDateTime(formater.format(newDate));        
                    //パターン"2009-06-30T20:55:00"を使ったラインを挿入

                    System.out.println(">>              >> creating REANIMATION event");
                    System.out.println(">>              >> event starttime: " + formater.format(newDate));

                    newDate.setTime(newDate.getTime() + 1000 * 60 * 0); //再び現在の時間 
                                                                        // + 1分を追加 
                    endTime = DateTime.parseDateTime(formater.format(newDate));

                    System.out.println(">>              >> event stoptime : " + formater.format(newDate));

                    eventTimes.setStartTime(startTime);
                    eventTimes.setEndTime(endTime);
                    myEntry.addTime(eventTimes);

                    reminderMinutes = 0;  //1分前をリマインド

                    reminder.setMinutes(reminderMinutes);
                    reminder.setMethod(methodType);
                    myEntry.getReminder().add(reminder);

                    //新しいカレンダーサビスの作成、グーグルに接続
                    CalendarService tempService = new CalendarService("My Application");
                    tempService.setUserCredentials(args[0], args[1]);     //引数としてのログインとパスワード
                    //順番にイベントをPUT
                    tempService.insert(feedUrl, myEntry);
                }
            }

            //新しいカレンダーサビスの作成、グーグルに接続
            CalendarService basicService = new CalendarService("basic Application");
            basicService.setUserCredentials(args[0], args[1]);             //引数としてのログインとパスワード

            //新イベント作成
            CalendarEventEntry basicEntry = new CalendarEventEntry();
            basicEntry.setTitle(new PlainTextConstruct(alertTxt));        //タイトル設定

            if (mode == 0) {    //標準的な日のシチュエーション
                newDate.setTime(newDate.getTime() + 1000 * 60 * timePeriod);  //現在時刻 + timePeriod 分
                startTime = DateTime.parseDateTime(formater.format(newDate));
                //パターン"2009-06-30T20:55:00"を使ったラインを挿入

                newDate.setTime(newDate.getTime() + 1000 * 60 * 0); //再び現在の時間
                                                                    // + timePeriod 分
                endTime = DateTime.parseDateTime(formater.format(newDate));
            }
            if (mode == 1) {    //翌朝か月曜午前のためのスケジュールイベント
                Date curDate = new Date();
                GregorianCalendar gDate = new GregorianCalendar();
                gDate.setTime(curDate);
                //要求した時間・分の設定
                gDate.set(GregorianCalendar.HOUR_OF_DAY, startHour);
                gDate.set(GregorianCalendar.MINUTE, startMin);
                gDate.set(GregorianCalendar.SECOND, 0);

                if (gDate.get(GregorianCalendar.DAY_OF_WEEK) < 6) {    // MO - THU
                    gDate.set(GregorianCalendar.DAY_OF_MONTH, gDate.get(GregorianCalendar.DAY_OF_MONTH) + 1);
                } else {    // MO
                    gDate.set(GregorianCalendar.DAY_OF_MONTH, gDate.get(GregorianCalendar.DAY_OF_MONTH) + 3);
                }
                // System.out.println("gDate "+ gDate.getTime());
                startTime = DateTime.parseDateTime(formater.format(gDate.getTime()));
                gDate.set(GregorianCalendar.MINUTE, gDate.get(GregorianCalendar.MINUTE) + timePeriod);
                endTime = DateTime.parseDateTime(formater.format(gDate.getTime()));
                System.out.println(">> nextday event should be created");
            }
            //System.out.println("creating ALERT event!");
            System.out.println(">> creating ALERT event");
            System.out.println(">> event starttime: " + startTime.toString());
            System.out.println(">> event stoptime : " + endTime.toString());

            eventTimes.setStartTime(startTime);
            eventTimes.setEndTime(endTime);
            basicEntry.addTime(eventTimes);

            reminderMinutes = 0;  //1分前をリマインド

            reminder.setMinutes(reminderMinutes);
            reminder.setMethod(methodType);
            basicEntry.getReminder().add(reminder);

            //順番にイベントをPUT
            basicService.insert(feedUrl, basicEntry);

            System.out.println(">>----------  Finish  ----------<<");
        }
        catch (AuthenticationException e) {
            e.printStackTrace();
        }
        catch (MalformedURLException e) {
            e.printStackTrace();
        }
        catch (ServiceException e) {
            e.printStackTrace();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }
}

.batファイルコード

.batファイルをMQL4で作成するのは現在不可能なので、異なるモード2つの.batファイルを使用します。

@rem +-----------------------------------------------------------------------------------------+
@rem |         アプリケーションがSMSを送信                                                           |
@rem |      ------------------------------------------------------                             |
@rem | Rules:                                                                                  |
@rem |                                                                                         |
@rem | USER   -   送信者のアカウント                                                               |
@rem | PASS   -  送信者のパスワード                                                               |
@rem | ALER   -  アラート、アラートメッセージのテキスト                                                  |
@rem |              (ラテン文字のみを使用)                                                         |
@rem | REAN   -  復元、再接続について知らせるメッセージのテキスト                                        |
@rem |                  (ラテン文字のみを使用)                                                     |
@rem | STOP   -  ストップ、ブログラム実行の中止を禁止する                                               |
@rem |                  イベントタイトル                                                            |
@rem |                  (ラテン文字のみを使用)                                                     |
@rem | PERI   -  ピリオド、アラートメッセージを送るためのピリオドタイマー                                     |
@rem | MODE   -  モード                                                                         |
@rem |                  (0 - スタンダード                                                         |
@rem |                   1 - 翌朝か月曜の朝の送信するメッセージの                                    |
@rem |                        スケジュール設定                                                   |
@rem | HOUR   -  メッセージの送信が要求された                                                       |
@rem |                  「翌朝か月曜の朝」の時間                                                    |
@rem | MINU   -  分、「翌朝...」の分                                                               |
@rem +-----------------------------------------------------------------------------------------+

@rem ECHO off

set USER=forex.myaccount
set PASS=mypassword
set ALER=Terminal_Alert
set REAN=Trading_Resolved
set STOP=STOP
set PERI=5
set MODE=0
set HOUR=8
set MINU=20

set ARGS= %USER% %PASS% %ALER% %REAN% %STOP% %PERI% %MODE% %HOUR% %MINU%
     
    java -jar "d:\Documents\forex\Deltabank Trader 4\TerminalWatch\terminalWatcher.jar" %ARGS% 

@rem ECHO %ARGS%

エキスパートアドバイザーコード

以下に紹介するコードの関数は、トレードシステムのルールによれば「スケジュールアクション」ブロックにおいて呼び出される必要があるでしょう。
トレードセッションの終わりに、翌朝にSMSをスケジュール設定する関数を呼び出します。
リンクは.linkでタグ付けされているので、コンソールウィンドウが開いた時にすぐ始まらないように「最短化したアイコン?」コールモードを設定できます。


//+------------------------------------------------------------------+
//| ステータスSMSを送信                                                 |
//+------------------------------------------------------------------+
int sendSMS()
{
      string destination = StringConcatenate(TerminalPath(),"\TerminalWatch\launch.lnk");
      ShellExecuteA(WindowHandle(Symbol(),0),"open", destination, NULL, NULL,1);
}
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| 翌朝にステータスSMSを送信                                            |
//+------------------------------------------------------------------+
int sendSMSnextDate()
{
      string destination = StringConcatenate(TerminalPath(),"\TerminalWatch\launch_next_date.lnk");
      ShellExecuteA(WindowHandle(Symbol(),0),"open", destination, NULL, NULL,1);
}
//+------------------------------------------------------------------+

短所

実際問題、ターミナルとクウォーツサーバ―、グーグルサーバ―の時計をオペレーションと同調させるのはとても難しいものです。そのため、エキスパートアドバイザーのコードにおいて以下の手法を使います。:SMSは8分タイマーで毎5分ごとにセット。この手法は95%のケースで機能しますがまだ5%のケースを解決しなければいけません。クリームに落ちたハエ程度の問題ではありますが。

まとめ

この手法に興味がありグーグルアカウントにサインアップする気になったら、私の洗練されてはいないシステムの可能性を簡単にチェックできます。
再度言いますが、本稿で紹介したJava言語の詳細の多くは完全に私が理解できるものではありません。私の同僚の開発者の大きな助力がありました(ありがとう、Dima!)のより正確に皆さんの全ての質問に答えることができないでしょう。
貴重な時間を割いて頂きありがとうございました!


本稿に寄せられたコメントを受けての変更

現在のバージョンはオペレーションロジックに関する komposterによる修正案を含んでいます。:

  • 復元、メッセージは送信されなければ削除されない。;

添付ファイルのTerminalWatch_03.rarを探して下さい。

MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/1376

添付されたファイル |
TerminalWatch_02.zip (1622.08 KB)
TerminalWatch_03.zip (1622.04 KB)
Lite_EXPERT2.mqh:エキスパートアドバイザー開発者のためのファンクションキット Lite_EXPERT2.mqh:エキスパートアドバイザー開発者のためのファンクションキット
本稿は「ポピュラーなトレードシステムに基づくエキスパートアドバイザーとトレーディングロボット最適化の錬金術」シリーズの続きです。読者はLite_EXPERT2.mqh fileのより多くの普遍的な関数ライブラリについて親しくなるでしょう。
ジグザグおよび ATR例によるクラスとしてのインディケータ実装 ジグザグおよび ATR例によるクラスとしてのインディケータ実装
インディケータを計算する最適な方法についての議論は尽きるところがありません。どこでインディケータ値を計算すべきでしょうか?インディケータ自体でしょうか、またはそのインディケータを使う Expert Advisor に全ロジックを埋め込むのがよいのでしょうか?本稿では、カスタムインディケータ iCustom のソースコードをExpert Advisor のコードに直接、または計算最適化スクリプトに移動し、そして prev_calculated 値をモデル化するバリアントの一つについて述べていきます。
Lite_EXPERT2.mqhファイル - EAの最適化の実践例 Lite_EXPERT2.mqhファイル - EAの最適化の実践例
この記事では、筆者はEA構築の具体例にて、Lite_EXPERT2.mqhファイルの関数の紹介を続けます。Average True Range (ATR)の指標値に基づいて明確にされる取引から取引へと変動する指値注文の使用案を検証します。
ランダムウォーク理論とトレンドインディケータ ランダムウォーク理論とトレンドインディケータ
ランダムウォークは現実のマーケットデータと実によく似ていますが、大きな特徴がいくつかあります。本稿ではコインン投げゲームを使用するシミュレーションでランダムウォークのプロパティを考察します。データのプロパティを調査するためトレンドインディケータを作成します。