トレーリングワンバー安値・高値の発注処理を自動化するEA

あーめんどくせえめんどくせえ、全てがめんどくせえ。

ども、とのです。

真性のめんどくさがりなので色々困った事があります。

せっかく10連休取ってもめんどくさいから家にこもるし、
家でゴロゴロしててEAのシグナルが来ても発注処理がめんどくさいからスルー

で、そういう時に限って正しいシグナルだったりするのね。

その上適当にオーダーかけてしまったものがルールに反してて結構痛い損失食らったり…

あーめんどくさい。

どこまでめんどくさいのか

前にシグナルが来たらメールを送るEAを作っていましたが、
どうめんどくさくてそこから先へ進めないのか、買いシグナルが点灯した場合を例として考えてみましょう。

  1. シグナルが正しいかどうか判断する
  2. エントリー値として1本前のバー高値を把握する
  3. ストップロス値として直近の安値を把握する
  4. エントリー値-ストップロス値から許容できるロット数を算出する
  5. 2回に分けて決済できるように逆指値注文を2つ発注する(分けられない最小ロット数だった場合発注しない)
  6. 発注したバーでヒットしなかった場合、毎回逆指値をそのバーの高値にずらす。
  7. ヒットしないまま短期DTオシレーターが陰転してしまった場合、オーダーを取り消す。

め、めんどくさすぎる…

とくに6.と7.が鬼畜。
4時間足で取引していたとしても、4時間毎に逆指値が刺さっているか、
DTオシレーターが陰転しているか確認してオーダーを変更するかどうか判断しなければならないのです。
寝てる時とかどうしようもない。

で、ヒットした後も面倒。

  1. 前のスイングの61.8%内部リトレースメントに達するか短期DTオシレーターが二回陰転した場合、2つ持ったポジションのうち一つのストップロスを1本前のバーの安値に動かし、以降バーが更新されるたびにずらす。
  2. 長期DTオシレーターのSK,SDが両方75%以上に達するか陰転した場合、残りのポジションのストップロスを1本前のバーの安値に動かし、以降バーが更新されるたびにずらす。

…書いてて思った。

俺このルールに則って売買できてない。

明らかにどこかしら端折ってますわ。
お金がかかってるというのに、ダメ人間ですね。

めんどくさい処理は自動化

でも腐ってもプログラマ、めんどくさいものは自動化して改善しよう、
ということで、以下前々回くらいから続くMT4のプログラムに関する記事です。

今日まで10連休でしたが、旅行にも行かずこれ作っていたんです!
…嘘です、ほとんどアニメ見ながらギター弾いてました…

できたのがこちら
DTOMail.mq4を改良し、メール送信昨日はそのままに発注処理を追加しています。
(同時にDTOMail.mq4のバグも直しています。)

とうとう発注処理自動化ということで普通にEAみたいな動きをしますので、
もしこれを使おうと思っている酔狂な方がいたとしてもかならず動作確認してください。
本来なら発注エラーが発生した場合の処理をもっと丁寧に書かなければならないのですが、
今回はただメールを送るだけで済ますというてけとーな作りになっています。

500行程度の小さなプログラムですが、解説しようとすると面倒なのでかいつまんで説明します。

完全なEAではない

extern bool AllowAutoTrade = False;

このEAは発注処理は自動化し、発注するかの判断もある程度行いますが、
フィボナッチリトレースメントの状態やエリオット波動のパターン認識までしてくれるわけではありません。
その部分を自分で判断して、行けると判断した場合のみこのextern変数をtrueに変えて動作させます。

自動発注処理

      OpenLevel = Low[1] + Slippage * Point;
      StopLossLevel = High[iHighest(NULL, ShortTimeFrameInt, MODE_HIGH, FirstStopLossBarCount, 1)] + Point;
      // ストップロスが近すぎる場合は設置可能な最低限の場所へ移動
      if ((StopLossLevel - Ask) < (MarketInfo(Symbol(), MODE_STOPLEVEL) * Point + Slippage * Point)) {
         StopLossLevel = NormalizeDouble(Ask + (MarketInfo(Symbol(), MODE_STOPLEVEL) * Point + Slippage * Point), Digits);
      }
      StopLossValue = StopLossLevel - Ask;
      // 逆指値が近すぎる場合は即時オープン
      if ((Bid - OpenLevel) < (MarketInfo(Symbol(), MODE_STOPLEVEL) * Point + Slippage * Point)) {
         SendOrderType = OP_SELL;
         OpenLevel = Bid;
      } else {
         SendOrderType = OP_SELLSTOP;
      }

発注を行うための逆指値、ストップロスの値を決める部分です。
Mt4は逆指値、ストップロスの値が近すぎるとOrderSend Error 130を返してしまうため、
MarketInfo(Symbol(), MODE_STOPLEVEL)を見て値が近すぎれば発注可能な値まで移動させています。

   // ロット数は口座残高のリスク%÷1ロット分ストップロスにかかった場合の口座通貨における損失額(ストップロス価格差×1ティックの口座通貨における金額)
   Lots = NormalizeDouble((AccountBalance() * (Risk / 100.0)) 
       / ((StopLossValue /  MarketInfo(Symbol(), MODE_TICKSIZE))
         * MarketInfo(Symbol(), MODE_TICKVALUE)), LotDigits);

ロット数を算出する処理です。
いんたーねっとをけんさくしたらでてきました。

ただ、この方法通貨単位がUSDのFXだとだいたい使えるんですが、
通貨単位がJPYのCFDとかだと途端にどでかいポジションを取ろうとしてOrderSend error 134 を返してしまいます。
Riskの値を1/100しましょう。
銘柄によってはさらにRisk値を下げる必要があります。

正しい計算方法が未だ分からんので、USDベースでバックテストを行って動作確認してみてください。

ロジックを修正して正しい値で計算できるようにしました。
コメントにも書いてあるとおり、
ロット数の算出式は
口座残高のリスク% ÷ 1ロット分ストップロスにかかった場合の口座通貨における損失額
で、
1ロット分ストップロスにかかった場合の口座通貨における損失額

ストップロス価格差×1ティックの口座通貨における金額
で求められます。
ストップロス価格差はティック値で求める必要があるためMarketInfo(Symbol(), MODE_TICKSIZE)で割っています。

トレーリングワンバー高値

         if(LongSK > LongSD && ShortSK_now > ShortSD_now) {
           OpenLevel = High[1] + Slippage * Point;
           if(OrderOpenPrice() > OpenLevel) {
              OrderModify(OrderTicket(), OpenLevel, OrderStopLoss() , OrderTakeProfit(), 0, MediumSeaGreen);
           }
         } else {
           OrderDelete(OrderTicket());
         }

めんどくさいと言っていたトレール処理です。
プログラムで書いてしまうと簡単で、シグナルが継続している限り、OrderModifyをするだけです。

シグナルが反転した場合はOrderDeleteします。

ポジションを持った後のストップロストレールも同じような感じで行っています。

ここまでの自動化はちと怖いけど

全然解説できてないけど眠くなってきたのでここまで。
明日から仕事だし。
気が向いたら追記します。

発注処理の自動化は暴走すると大量にポジション取ったり意図しないところで決k際したりして大変なことになるので、
使うのは慎重にならないといけません。

ただ、現在の手動トレードに比べれば百万倍マシなので、
少しずつ改良しながら使っていこうかと思います。

(追記)
2013/09/26:ロット算出処理を中心にちょっと改良しました。

ソース全文

<

pre>
#property copyright "Tono"

#define SIGNAL_NONE 0
#define SIGNAL_BUY 1
#define SIGNAL_SELL 2
#define SIGNAL_CLOSEBUY 3
#define SIGNAL_CLOSESELL 4

#define DTO_SK 0
#define DTO_SD 1

extern bool AllowAutoTrade = False;
int FirstStopLossBarCount = 34;

extern string LongTimeFrame = "D1";
extern int LongPattern = 1;

int LongPeriodRSI =8;
int LongPeriodStoch= 5;
int LongPeriodSK = 3;
int LongPeriodSD = 3;
int LongMAMode = 0;

extern string ShortTimeFrame = "H4";
extern int ShortPattern = 1;

int ShortPeriodRSI =8;
int ShortPeriodStoch= 5;
int ShortPeriodSK = 3;
int ShortPeriodSD = 3;
int ShortMAMode = 0;

extern int MagicNumber = 12345;
extern double Risk = 1;
extern int Slippage = 5;

int BarCount;
int Current;
bool TickCheck = False;
bool SignalMail = True;
bool EachTickMode = False;
int LongTimeFrameInt = 1440;
int ShortTimeFrameInt =240;
int Order = 0;
int LotDigits;
bool IsTrading = False;

string title;
string message;

double LongSK;
double LongSD;
double ShortSK_now;
double ShortSD_now;
double ShortSK_before;
double ShortSD_before;

int i = 0;
//+------------------------------------------------------------------+
//| expert initialization function |
//+------------------------------------------------------------------+
int init() {
BarCount = Bars - 1;

if (EachTickMode) Current = 0; else Current = 1;

LongPeriodRSI =8;
LongPeriodStoch= 5;
LongPeriodSK = 3;
LongPeriodSD = 3;
ShortPeriodRSI =8;
ShortPeriodStoch= 5;
ShortPeriodSK = 3;
ShortPeriodSD = 3;

for (int i = 0; i < LongPattern; i++) {
int LongNewRSI = LongPeriodRSI + LongPeriodStoch;
LongPeriodSD = LongPeriodStoch;
LongPeriodSK = LongPeriodStoch;
LongPeriodStoch = LongPeriodRSI;
LongPeriodRSI = LongNewRSI;
}

for (i = 0; i < ShortPattern; i++) {
int ShortNewRSI = ShortPeriodRSI + ShortPeriodStoch;
ShortPeriodSD = ShortPeriodStoch;
ShortPeriodSK = ShortPeriodStoch;
ShortPeriodStoch = ShortPeriodRSI;
ShortPeriodRSI = ShortNewRSI;
}

if (LongTimeFrame=="M1" || LongTimeFrame=="1") LongTimeFrameInt=PERIOD_M1;
if (LongTimeFrame=="M5" || LongTimeFrame=="5") LongTimeFrameInt=PERIOD_M5;
if (LongTimeFrame=="M15"|| LongTimeFrame=="15") LongTimeFrameInt=PERIOD_M15;
if (LongTimeFrame=="M30"|| LongTimeFrame=="30") LongTimeFrameInt=PERIOD_M30;
if (LongTimeFrame=="H1" || LongTimeFrame=="60") LongTimeFrameInt=PERIOD_H1;
if (LongTimeFrame=="H4" || LongTimeFrame=="240") LongTimeFrameInt=PERIOD_H4;
if (LongTimeFrame=="D1" || LongTimeFrame=="1440") LongTimeFrameInt=PERIOD_D1;
if (LongTimeFrame=="W1" || LongTimeFrame=="10080") LongTimeFrameInt=PERIOD_W1;
if (LongTimeFrame=="MN" || LongTimeFrame=="43200") LongTimeFrameInt=PERIOD_MN1;
if (LongTimeFrameInt<Period()) LongTimeFrameInt=Period();

if (ShortTimeFrame=="M1" || ShortTimeFrame=="1") ShortTimeFrameInt=PERIOD_M1;
if (ShortTimeFrame=="M5" || ShortTimeFrame=="5") ShortTimeFrameInt=PERIOD_M5;
if (ShortTimeFrame=="M15"|| ShortTimeFrame=="15") ShortTimeFrameInt=PERIOD_M15;
if (ShortTimeFrame=="M30"|| ShortTimeFrame=="30") ShortTimeFrameInt=PERIOD_M30;
if (ShortTimeFrame=="H1" || ShortTimeFrame=="60") ShortTimeFrameInt=PERIOD_H1;
if (ShortTimeFrame=="H4" || ShortTimeFrame=="240") ShortTimeFrameInt=PERIOD_H4;
if (ShortTimeFrame=="D1" || ShortTimeFrame=="1440") ShortTimeFrameInt=PERIOD_D1;
if (ShortTimeFrame=="W1" || ShortTimeFrame=="10080") ShortTimeFrameInt=PERIOD_W1;
if (ShortTimeFrame=="MN" || ShortTimeFrame=="43200") ShortTimeFrameInt=PERIOD_MN1;
if (ShortTimeFrameInt<Period()) ShortTimeFrameInt=Period();

LotDigits = MathLog(1.0/MarketInfo(Symbol(),MODE_MINLOT))/MathLog(10.0);
showAllowTrade();

return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function |
//+------------------------------------------------------------------+
int deinit() {
ObjectDelete("AllowAutoTade");
return(0);
}
//+------------------------------------------------------------------+
//| expert start function |
//+------------------------------------------------------------------+
int start() {
if (Bars == BarCount) return(0);
BarCount = Bars;
//+------------------------------------------------------------------+
//| Begin |
//+------------------------------------------------------------------+
SetVariables();
//showDebug();
if (AllowAutoTrade) {
checkTrade();
}
checkMail();
return(0);
}

/**
* 変数の内容をセットします。
*/
void SetVariables(){
LongSK = iCustom(NULL, 0, "DT Oscillator", LongTimeFrame, LongPeriodRSI, LongPeriodStoch, LongPeriodSK, LongPeriodSD, LongMAMode, 0, Current);
LongSD = iCustom(NULL, 0, "DT Oscillator", LongTimeFrame, LongPeriodRSI, LongPeriodStoch, LongPeriodSK, LongPeriodSD, LongMAMode, 1, Current);
ShortSK_now = iCustom(NULL, 0, "DT Oscillator", ShortTimeFrame, ShortPeriodRSI, ShortPeriodStoch, ShortPeriodSK, ShortPeriodSD, ShortMAMode,0, Current);
ShortSD_now = iCustom(NULL, 0, "DT Oscillator", ShortTimeFrame, ShortPeriodRSI, ShortPeriodStoch, ShortPeriodSK, ShortPeriodSD, ShortMAMode, 1, Current);
ShortSK_before= iCustom(NULL, 0, "DT Oscillator", ShortTimeFrame, ShortPeriodRSI, ShortPeriodStoch, ShortPeriodSK, ShortPeriodSD, ShortMAMode, 0, Current + 1);
ShortSD_before = iCustom(NULL, 0, "DT Oscillator", ShortTimeFrame, ShortPeriodRSI, ShortPeriodStoch, ShortPeriodSK, ShortPeriodSD, ShortMAMode, 1, Current + 1);
}

/**
* 売買を実行します。
*/
int checkTrade(){
Order = SIGNAL_NONE;
//Check position
IsTrading = checkExistTickets();
if (!IsTrading) {
checkNewTrade();
}
return(0);
}

/**
* チケットが存在するかを返します。
*/
bool checkExistTickets() {
bool IsTrade = False;
int Total = OrdersTotal();
int Tickets[2];
int TicketCount = 0;
for (int i = 0; i < Total; i++) {
OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
if(OrderSymbol() == Symbol() ) {
// 直接オープンした時にもクローズを行わせたいためMagicNumberは見ない
//&& OrderMagicNumber() == MagicNumber
IsTrade = True;
if (TicketCount >= 2) {
MailOrPrint("Error: " + Symbol() + " too many tickets ", "ticket count : " + TicketCount);
break;
}
Tickets[TicketCount] = OrderTicket();
TicketCount = TicketCount + 1;
}
}
if (TicketCount == 1) {
modifyLongTicket(Tickets[0]);
} else if (TicketCount == 2) {
modifyWhenTwoTicket(Tickets);
}
if (IsTrading && !IsTrade) {
MailOrPrint("Order closed: " + Symbol(), "Order closed: " + Symbol());
}
return(IsTrade);
}

/**
* 2つのチケットがある場合(注文中もしくは短期ポジ持ち)に注文を修正します。
*/
void modifyWhenTwoTicket(int Tickets[]) {
double StopLossLevel, OpenLevel;
for (int i = 0; i < 2; i++) {
OrderSelect(Tickets[i], SELECT_BY_TICKET, MODE_TRADES);
if(OrderType() == OP_BUY) {
if(isTrailShortTimeFramePosition()) {
StopLossLevel = Low[1] - Point * Slippage;
if(OrderStopLoss() < StopLossLevel) {
OrderModify(OrderTicket(), OrderOpenPrice(), StopLossLevel, OrderTakeProfit(), 0, MediumSeaGreen);
}
}
// 1つだけ
break;
} else if (OrderType() == OP_SELL) {
if(isTrailShortTimeFramePosition()) {
StopLossLevel = High[1] + Point * Slippage;
if(OrderStopLoss() > StopLossLevel) {
OrderModify(OrderTicket(), OrderOpenPrice(), StopLossLevel , OrderTakeProfit(), 0, DarkOrange);
}
}
// 1つだけ
break;
} else if (OrderType() == OP_BUYSTOP) {
if(LongSK > LongSD && ShortSK_now > ShortSD_now) {
OpenLevel = High[1] + Point;
StopLossLevel = Low[iLowest(NULL, ShortTimeFrameInt, MODE_LOW, FirstStopLossBarCount, 1)] - Point;
if(OrderOpenPrice() > OpenLevel) {
OrderModify(OrderTicket(), OpenLevel, StopLossLevel , OrderTakeProfit(), 0, MediumSeaGreen);
}
} else {
OrderDelete(OrderTicket());
}
} else if (OrderType() == OP_SELLSTOP) {
if(LongSK < LongSD && ShortSK_now < ShortSD_now) {
OpenLevel = Low[1] - Point;
StopLossLevel = High[iHighest(NULL, ShortTimeFrameInt, MODE_HIGH, FirstStopLossBarCount, 1)] + Point;
if(OrderOpenPrice() < OpenLevel) {
OrderModify(OrderTicket(), OpenLevel, StopLossLevel, OrderTakeProfit(), 0, DarkOrange);
}
} else {
OrderDelete(OrderTicket());
}
}
}
}

/**
* 短期ポジションのストップを動かすべきかを調べます。
* 短期DTオシレーターが2回逆方向へクロスしたかどうかで判定します。(ABC調整パターン形成完了後の反転)
*/
bool isTrailShortTimeFramePosition(){
int OpenBar = iBarShift(NULL, ShortTimeFrameInt, OrderOpenTime());
int ClossCount = 0;
bool Res = False;
double SK_now, SD_now, SK_before, SD_before = 0.0;
for (int i = OpenBar; i >= 0; i--) {
SK_before = SK_now;
SD_before = SD_now;
SK_now = iCustom(NULL, 0, "DT Oscillator", ShortTimeFrame, ShortPeriodRSI, ShortPeriodStoch, ShortPeriodSK, ShortPeriodSD, ShortMAMode,0, i);
SD_now = iCustom(NULL, 0, "DT Oscillator", ShortTimeFrame, ShortPeriodRSI, ShortPeriodStoch, ShortPeriodSK, ShortPeriodSD, ShortMAMode, 1, i);
if ((OrderType() == OP_BUY && SK_before > SD_before && SK_now < SD_now) ||
(OrderType() == OP_SELL && SK_before < SD_before && SK_now > SD_now)) {
ClossCount = ClossCount + 1;
}
if (ClossCount >= 2) {
Res = True;
break;
}
}
return(Res);
}

/**
* 長期ポジションのストップを移動します。
*/
void modifyLongTicket(int TicketNo) {
double StopLossLevel, OpenLevel;
OrderSelect(TicketNo, SELECT_BY_TICKET, MODE_TRADES);
if(OrderType() == OP_BUY) {
if((LongSK > 75 && LongSD > 75) || (LongSK < LongSD)) {
StopLossLevel = Low[1];
if(OrderStopLoss() < StopLossLevel) {
OrderModify(OrderTicket(), OrderOpenPrice(), StopLossLevel, OrderTakeProfit(), 0, MediumSeaGreen);
}
}
} else if (OrderType() == OP_SELL) {
if((LongSK < 25 && LongSD < 25) || (LongSK > LongSD)) {
StopLossLevel = High[1];
if(OrderStopLoss() > StopLossLevel) {
OrderModify(OrderTicket(), OrderOpenPrice(), StopLossLevel , OrderTakeProfit(), 0, DarkOrange);
}
}
} else {
MailOrPrint("Error " + Symbol() + ": only one stop ticket", "ticket No : " + TicketNo);
}
}

/**
* 新規のポジションを建てます。
*/
void checkNewTrade() {
double OpenLevel, StopLossLevel, StopLossValue, Lots, OneLot;
int Ticket, SendOrderType, ArrowColor;
if (EachTickMode) TickCheck = True;
//+------------------------------------------------------------------+
//| Signal Begin(Entry) |
//+------------------------------------------------------------------+

if ( LongSK > LongSD && !(LongSK > 75 && LongSD > 75)
&& ShortSK_now > ShortSD_now
&& ShortSK_before< ShortSD_before) {
Order = SIGNAL_BUY;
}

if ( LongSK < LongSD && !(LongSK < 25 && LongSD < 25)
&& ShortSK_now < ShortSD_now
&& ShortSK_before> ShortSD_before) {
Order = SIGNAL_SELL;
}

//+------------------------------------------------------------------+
//| Signal End |
//+------------------------------------------------------------------+

if (Order == SIGNAL_BUY) {
OpenLevel = High[1] + Slippage * Point;
StopLossLevel = Low[iLowest(NULL, ShortTimeFrameInt, MODE_LOW, FirstStopLossBarCount, 1)] - Point;
// ストップロスが近すぎる場合は設置可能な最低限の場所へ移動
if ((Bid - StopLossLevel) < (MarketInfo(Symbol(), MODE_STOPLEVEL) * Point + Slippage * Point)) {
StopLossLevel = NormalizeDouble(Bid - (MarketInfo(Symbol(), MODE_STOPLEVEL) * Point + Slippage * Point), Digits);
}
StopLossValue = Bid - StopLossLevel;
// 逆指値が近すぎる場合は即時オープン
if (OpenLevel - Ask < (MarketInfo(Symbol(), MODE_STOPLEVEL) * Point + Slippage * Point)) {
SendOrderType = OP_BUY;
OpenLevel = Ask;
} else {
SendOrderType = OP_BUYSTOP;
}
ArrowColor = DodgerBlue;
} else if (Order == SIGNAL_SELL) {
OpenLevel = Low[1] + Slippage * Point;
StopLossLevel = High[iHighest(NULL, ShortTimeFrameInt, MODE_HIGH, FirstStopLossBarCount, 1)] + Point;
// ストップロスが近すぎる場合は設置可能な最低限の場所へ移動
if ((StopLossLevel - Ask) < (MarketInfo(Symbol(), MODE_STOPLEVEL) * Point + Slippage * Point)) {
StopLossLevel = NormalizeDouble(Ask + (MarketInfo(Symbol(), MODE_STOPLEVEL) * Point + Slippage * Point), Digits);
}
StopLossValue = StopLossLevel - Ask;
// 逆指値が近すぎる場合は即時オープン
if ((Bid - OpenLevel) < (MarketInfo(Symbol(), MODE_STOPLEVEL) * Point + Slippage * Point)) {
SendOrderType = OP_SELL;
OpenLevel = Bid;
} else {
SendOrderType = OP_SELLSTOP;
}
ArrowColor = DeepPink;
} else {
return(0);
}

// ロット数は口座残高のリスク%÷1ロット分ストップロスにかかった場合の口座通貨における損失額(ストップロス価格差×1ティックの口座通貨における金額)
Lots = NormalizeDouble((AccountBalance() * (Risk / 100.0))
/ ((StopLossValue / MarketInfo(Symbol(), MODE_TICKSIZE))
* MarketInfo(Symbol(), MODE_TICKVALUE)), LotDigits);
OneLot = NormalizeDouble((Lots / 2.0), LotDigits);
//四捨五入されてしまうので、残りと比較して小さい方を選ぶ
if (OneLot > (Lots - OneLot)) {
OneLot = Lots - OneLot;
}
if (OneLot < MarketInfo(Symbol(),MODE_MINLOT)) {
MailOrPrint("Error: " + Symbol() + " Lots is under minlot", "Lots:" + DoubleToStr(Lots, LotDigits) + "\nMinLot:" + MarketInfo(Symbol(),MODE_MINLOT));
return(0);
}
Ticket = OrderSend(Symbol(), SendOrderType, OneLot, OpenLevel, Slippage, StopLossLevel, 0, "New Order:" + MagicNumber, MagicNumber, 0, ArrowColor);
checkSendOrder(Ticket);
Ticket = OrderSend(Symbol(), SendOrderType, (Lots - OneLot), OpenLevel, Slippage, StopLossLevel, 0, "New Oorder:" + MagicNumber, MagicNumber, 0, ArrowColor);
checkSendOrder(Ticket);
return(0);
}

/**
* 注文が通ったか確認します。
*/
void checkSendOrder(int Ticket) {
if(Ticket > 0) {
if (OrderSelect(Ticket, SELECT_BY_TICKET, MODE_TRADES)) {
string type;
if (OrderType() == OP_BUYSTOP) type = "Buy"; else type = "Sell";
Print(type + " order opened : ", OrderOpenPrice());
if (SignalMail) MailOrPrint("[Signal Alert]", "[" + Symbol() + "] " + DoubleToStr(Ask, Digits) + " Open " + type);
}
} else {
Print("Error: " + Symbol() + " opening order : ", GetLastError());
}
}

/**
* シグナル発生を確認してメールを送信します。
*/
int checkMail(){
if (!(LongSK > 75 && LongSD > 75) && ((LongSK > LongSD)) &&
ShortSK_before< ShortSD_before && ShortSK_now > ShortSD_now) {
MakeMessageBuy();
MailAndArrow(SIGNAL_BUY, "B");
} else if (!(LongSK < 25 && LongSD < 25) && ((LongSK < LongSD)) &&
ShortSK_before> ShortSD_before && ShortSK_now < ShortSD_now) {
MakeMessageSell();
MailAndArrow(SIGNAL_SELL, "S");
}
return(0);
}

/**
* 買いシグナルのメッセージを作成します。
*/
void MakeMessageBuy() {
title = "Buy Signal " + Symbol() + " " + Period();
message = "[Buy Signal]\n"
+ "[" + Symbol() + "] \n"
+ "Price:" + DoubleToStr(Ask, Digits) + "\n"
+ MakeHighLow();
}

/**
* 売りシグナルのメッセージを作成します。
*/
void MakeMessageSell() {
title = "Sell Signal " + Symbol() + " " + Period();
message = "[Sell Signal]\n"
+ "[" + Symbol() + "] \n"
+ "Price:" + DoubleToStr(Ask, Digits) + "\n"
+ MakeHighLow();
}

string MakeHighLow() {
string highLow = "";
for (int i = 1; i < 11; i++) {
highLow = (highLow + "high" + i + ":" + High[i] + " low" + i + ":" + Low[i] + "\n");
}
return (highLow);
}

/**
* メールを送信し、直近のバーに矢印を置きます。
*/
void MailAndArrow(int signal, string str) {
MailOrPrint(title, message);
string name = "arrow" + i;
ObjectCreate(name, OBJ_TEXT, 0, Time[1], Close[1]);

if (signal == SIGNAL_BUY) {
ObjectSetText(name, str , 14, "Verdana", White);
ObjectSet(name, OBJPROP_COLOR, Magenta);
} else {
ObjectSetText(name, str , 14 , "Verdana", White);
ObjectSet(name, OBJPROP_COLOR, Turquoise);
}
i = i + 1;
}

/**
* メールを送信します。
* テストモードの時にはPrintを行います。
*/
void MailOrPrint(string ttl, string msg) {
if (IsTesting()) {
Print("Mailed. title:" + ttl + " message:" + msg);
} else {
SendMail(ttl, msg);
}
}

/**
* 売買が許可されているかを表示します。
*/
void showAllowTrade() {
string str = "";
int height = 10;

height += 20;
if (AllowAutoTrade) {
str = "Auto Trading!";
ObjectCreate("AllowAutoTrade", OBJ_LABEL, 0, 0, 0);
ObjectSetText("AllowAutoTrade", str, 10, "Verdana", Red);
ObjectSet("AllowAutoTrade", OBJPROP_CORNER, 0);
ObjectSet("AllowAutoTrade", OBJPROP_XDISTANCE, 20);
ObjectSet("AllowAutoTrade", OBJPROP_YDISTANCE, height);
} else {
ObjectDelete("AllowAutoTade");
}
}

void showDebug() {
string str = "";
int height = 20;

height += 20;
str = "LongSK: " + DoubleToStr(LongSK, 0);

ObjectCreate("LongSK", OBJ_LABEL, 0, 0, 0);
ObjectSetText("LongSK", str, 10, "Verdana", White);
ObjectSet("LongSK", OBJPROP_CORNER, 0);
ObjectSet("LongSK", OBJPROP_XDISTANCE, 20);
ObjectSet("LongSK", OBJPROP_YDISTANCE, height);

height += 20;
str = "LongSD: " + DoubleToStr(LongSD, 0);

ObjectCreate("LongSD", OBJ_LABEL, 0, 0, 0);
ObjectSetText("LongSD", str, 10, "Verdana", White);
ObjectSet("LongSD", OBJPROP_CORNER, 0);
ObjectSet("LongSD", OBJPROP_XDISTANCE, 20);
ObjectSet("LongSD", OBJPROP_YDISTANCE, height);

height += 20;
str = "ShortSK_now: " + DoubleToStr(ShortSK_now, 0);

ObjectCreate("ShortSK_now", OBJ_LABEL, 0, 0, 0);
ObjectSetText("ShortSK_now", str, 10, "Verdana", White);
ObjectSet("ShortSK_now", OBJPROP_CORNER, 0);
ObjectSet("ShortSK_now", OBJPROP_XDISTANCE, 20);
ObjectSet("ShortSK_now", OBJPROP_YDISTANCE, height);

height += 20;
str = "ShortSD_now: " + DoubleToStr(ShortSD_now, 0);

ObjectCreate("ShortSD_now", OBJ_LABEL, 0, 0, 0);
ObjectSetText("ShortSD_now", str, 10, "Verdana", White);
ObjectSet("ShortSD_now", OBJPROP_CORNER, 0);
ObjectSet("ShortSD_now", OBJPROP_XDISTANCE, 20);
ObjectSet("ShortSD_now", OBJPROP_YDISTANCE, height);

height += 20;
str = "ShortSK_before: " + DoubleToStr(ShortSK_before, 0);

ObjectCreate("ShortSK_before", OBJ_LABEL, 0, 0, 0);
ObjectSetText("ShortSK_before", str, 10, "Verdana", White);
ObjectSet("ShortSK_before", OBJPROP_CORNER, 0);
ObjectSet("ShortSK_before", OBJPROP_XDISTANCE, 20);
ObjectSet("ShortSK_before", OBJPROP_YDISTANCE, height);

height += 20;
str = "ShortSD_before: " + DoubleToStr(ShortSD_before, 0);

ObjectCreate("ShortSD_before", OBJ_LABEL, 0, 0, 0);
ObjectSetText("ShortSD_before", str, 10, "Verdana", White);
ObjectSet("ShortSD_before", OBJPROP_CORNER, 0);
ObjectSet("ShortSD_before", OBJPROP_XDISTANCE, 20);
ObjectSet("ShortSD_before", OBJPROP_YDISTANCE, height);
}
//+------------------------------------------------------------------+


投稿日

カテゴリー:

投稿者:

コメント

“トレーリングワンバー安値・高値の発注処理を自動化するEA” への2件のフィードバック

  1. やしまのアバター
    やしま

    とのさんはじめまして、やしまです。
    私もフィボナッチブレイクアウト売買法を7月くらいに読んで、
    非常に完成された、売買ルールに魅了され、完全にこれ一本で投資しようとしてます。
    ただ、エリオット波動の数の数え方とかに時間が取られて、まだ検証の段階です。

    この手法で取引してる人、いるんでしょうが、ネットで検索しても全く出てきませんね。
    私はDTオシレーターで検索して、とのさんのブログに辿り着きました。
    DTオシレーターのプログラムは私も使わせてもらってます。

    ソースをだいたい理解できたので、
    少しいじりながらですがありがたく使わせてもらってますよ!

    ただ、どこがエラーなのかとか、わからないんですがね。
    非常に興味深くブログを何回も読ませていただいていますので
    これからもよろしくおねがいしますね

    またコメントします
    では

    1. とののアバター
      との

      やしまさん
      コメントありがとうございます!
      ブログ放置気味でした…
      本業が忙しくて、という言い訳ですすみません(^_^;)

      確かに、この手法はあまり使われていませんよね。
      エリオット波動と時間論の判定の仕方に裁量が入るので扱いが若干難しいです。

      ZigZag使ってEA化も試してみましたけど利益出ません…
      ココらへんは年末年始で上げられればなぁと思います。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください