#property copyright "Copyright 2013, Zoltan Tarsoly"
#property link "tarsolyz@t-online.hu"

extern bool draw_patterns = true;
extern int session_first_hour = 9;
extern int session_last_hour = 17;
extern int magic_number = 9999;
extern color upper_pattern_color = Blue;
extern color lower_pattern_color = Red;
extern color joint_pattern_color = Magenta;
extern double extra_price = 0.00010;
extern double spread_price = 0.00015;
extern double risk_to_reward_ratio = 1.0;

datetime last_run_time;
string trendline_names[4] = {"Upper 123 Pattern 1st Line", "Upper 123 Pattern 2nd Line", "Lower 123 Pattern 1st Line", "Lower 123 Pattern 2nd Line"};

int init() {
  return(0);
}

int deinit() {
  if (ObjectFind(trendline_names[0]) >= 0)
    ObjectDelete(trendline_names[0]);
  if (ObjectFind(trendline_names[1]) >= 0)
    ObjectDelete(trendline_names[1]);
  if (ObjectFind(trendline_names[2]) >= 0)
    ObjectDelete(trendline_names[2]);
  if (ObjectFind(trendline_names[3]) >= 0)
    ObjectDelete(trendline_names[3]);
  return(0);
}

void SetPatterns(int& pattern_indexies[2][3], int last_bar_index) {
  int i;
  ArrayInitialize(pattern_indexies, -1);
  while (((pattern_indexies[0][0] < 0) || (pattern_indexies[0][1] < 0) || (pattern_indexies[0][2] < 0) || (pattern_indexies[1][0] < 0) || (pattern_indexies[1][1] < 0) || (pattern_indexies[1][2] < 0)) && (i <= last_bar_index)) {
    if (iFractals(NULL, 0, MODE_UPPER, i) > 0) {
      if ((pattern_indexies[0][0] >= 0) && ((pattern_indexies[0][1] < 0) || (High[i] > High[pattern_indexies[0][1]])) && (pattern_indexies[0][2] < 0) && (i != pattern_indexies[0][0]))
        pattern_indexies[0][1] = i;
      if (pattern_indexies[1][0] < 0)
        pattern_indexies[1][0] = i;
      else if ((pattern_indexies[1][1] >= 0) && (pattern_indexies[1][2] < 0) && (High[i] > High[pattern_indexies[1][0]]) && (i != pattern_indexies[1][1]))
        pattern_indexies[1][2] = i;
    }
    if (iFractals(NULL, 0, MODE_LOWER, i) > 0) {
      if ((pattern_indexies[1][0] >= 0) && ((pattern_indexies[1][1] < 0) || (Low[i] < Low[pattern_indexies[1][1]])) && (pattern_indexies[1][2] < 0) && (i != pattern_indexies[1][0]))
        pattern_indexies[1][1] = i;
      if (pattern_indexies[0][0] < 0)
        pattern_indexies[0][0] = i;
      else if ((pattern_indexies[0][1] >= 0) && (pattern_indexies[0][2] < 0) && (Low[i] < Low[pattern_indexies[0][0]]) && (i != pattern_indexies[0][1]))
        pattern_indexies[0][2] = i;
    }
    i++;
  }
  if (draw_patterns) {
    if (ObjectFind(trendline_names[0]) >= 0)
      ObjectDelete(trendline_names[0]);
    ObjectCreate(trendline_names[0], OBJ_TREND, 0, Time[pattern_indexies[0][1]], High[pattern_indexies[0][1]], Time[pattern_indexies[0][0]], Low[pattern_indexies[0][0]]);
    if ((pattern_indexies[0][0] == pattern_indexies[1][1]) && (pattern_indexies[0][1] == pattern_indexies[1][2]))
      ObjectSet(trendline_names[0], OBJPROP_COLOR, joint_pattern_color);
    else
      ObjectSet(trendline_names[0], OBJPROP_COLOR, upper_pattern_color);
    ObjectSet(trendline_names[0], OBJPROP_RAY, 0);
    if (ObjectFind(trendline_names[1]) >= 0)
      ObjectDelete(trendline_names[1]);
    ObjectCreate(trendline_names[1], OBJ_TREND, 0, Time[pattern_indexies[0][2]], Low[pattern_indexies[0][2]], Time[pattern_indexies[0][1]], High[pattern_indexies[0][1]]);
    if ((pattern_indexies[0][1] == pattern_indexies[1][0]) && (pattern_indexies[0][2] == pattern_indexies[1][1]))
      ObjectSet(trendline_names[1], OBJPROP_COLOR, joint_pattern_color);
    else
      ObjectSet(trendline_names[1], OBJPROP_COLOR, upper_pattern_color);
    ObjectSet(trendline_names[1], OBJPROP_RAY, 0);
    if (ObjectFind(trendline_names[2]) >= 0)
      ObjectDelete(trendline_names[2]);
    ObjectCreate(trendline_names[2], OBJ_TREND, 0, Time[pattern_indexies[1][1]], Low[pattern_indexies[1][1]], Time[pattern_indexies[1][0]], High[pattern_indexies[1][0]]);
    if ((pattern_indexies[1][0] == pattern_indexies[0][1]) && (pattern_indexies[1][1] == pattern_indexies[0][2]))
      ObjectSet(trendline_names[2], OBJPROP_COLOR, joint_pattern_color);
    else
      ObjectSet(trendline_names[2], OBJPROP_COLOR, lower_pattern_color);
    ObjectSet(trendline_names[2], OBJPROP_RAY, 0);
    if (ObjectFind(trendline_names[3]) >= 0)
      ObjectDelete(trendline_names[3]);
    ObjectCreate(trendline_names[3], OBJ_TREND, 0, Time[pattern_indexies[1][2]], High[pattern_indexies[1][2]], Time[pattern_indexies[1][1]], Low[pattern_indexies[1][1]]);
    if ((pattern_indexies[1][1] == pattern_indexies[0][0]) && (pattern_indexies[1][2] == pattern_indexies[0][1]))
      ObjectSet(trendline_names[3], OBJPROP_COLOR, joint_pattern_color);
    else
      ObjectSet(trendline_names[3], OBJPROP_COLOR, lower_pattern_color);
    ObjectSet(trendline_names[3], OBJPROP_RAY, 0);
  }
}

int start() {
  bool have_buy_order;
  bool have_sell_order;
  bool is_trade_time = (TimeHour(Time[0]) >= session_first_hour) && (TimeHour(Time[0]) <= session_last_hour);
  int i;
  int ticket;
  int pattern_indexies[2][3] = {-1, -1, -1, -1, -1, -1};
  double open_price;
  double stop_loss_price;
  double take_profit_price;
  double upper_pivot_price;
  double lower_pivot_price;
  if (last_run_time < Time[0]) {
    last_run_time = Time[0];
    SetPatterns(pattern_indexies, Bars - 1);
    upper_pivot_price = High[pattern_indexies[0][1]];
    lower_pivot_price = Low[pattern_indexies[1][1]];
    for (i = OrdersTotal() - 1; i >= 0; i--)
      if (OrderSelect(i, SELECT_BY_POS)) {
        if (OrderMagicNumber() == magic_number)
          switch (OrderType()) {
            case OP_BUY:
              have_buy_order = true;
              break;
            case OP_BUYSTOP:
              have_buy_order = true;
              if ((upper_pivot_price > High[iHighest(NULL, 0, pattern_indexies[0][1], 0)]) && (upper_pivot_price > iMA(NULL, 0, 34, 0, MODE_EMA, PRICE_HIGH, pattern_indexies[0][1])) && (upper_pivot_price > iMA(NULL, 0, 89, 0, MODE_EMA, PRICE_CLOSE, pattern_indexies[0][1])) && is_trade_time) {
                open_price = NormalizeDouble(upper_pivot_price + spread_price + extra_price, Digits);
                stop_loss_price = NormalizeDouble(Low[pattern_indexies[0][2]] - extra_price, Digits);
                take_profit_price = NormalizeDouble(open_price + (open_price - stop_loss_price) / risk_to_reward_ratio, Digits);
                if ((open_price != NormalizeDouble(OrderOpenPrice(), Digits)) || (stop_loss_price != NormalizeDouble(OrderStopLoss(), Digits)) || (take_profit_price != NormalizeDouble(OrderTakeProfit(), Digits)))
                  if (!OrderModify(OrderTicket(), open_price, stop_loss_price, take_profit_price, 0))
                    Alert("Error: OrderModify!");
              }
              break;
            case OP_SELL:
              have_sell_order = true;
              break;
            case OP_SELLSTOP:
              have_sell_order = true;
              if ((lower_pivot_price < Low[iLowest(NULL, 0, pattern_indexies[1][1], 0)]) && (lower_pivot_price < iMA(NULL, 0, 34, 0, MODE_EMA, PRICE_LOW, pattern_indexies[1][1])) && (lower_pivot_price < iMA(NULL, 0, 89, 0, MODE_EMA, PRICE_CLOSE, pattern_indexies[1][1])) && is_trade_time) {
                open_price = NormalizeDouble(lower_pivot_price - extra_price, Digits);
                stop_loss_price = NormalizeDouble(High[pattern_indexies[1][2]] + spread_price + extra_price, Digits);
                take_profit_price = NormalizeDouble(open_price - (stop_loss_price - open_price) / risk_to_reward_ratio + spread_price, Digits);
                if ((open_price != NormalizeDouble(OrderOpenPrice(), Digits)) || (stop_loss_price != NormalizeDouble(OrderStopLoss(), Digits)) || (take_profit_price != NormalizeDouble(OrderTakeProfit(), Digits)))
                  if (!OrderModify(OrderTicket(), open_price, stop_loss_price, take_profit_price, 0))
                    Alert("Error: OrderModify!");
              }
              break;
          }
      }
      else
        Alert("Error: OrderSelect!");
    if ((upper_pivot_price > High[iHighest(NULL, 0, pattern_indexies[0][1], 0)]) && (upper_pivot_price > iMA(NULL, 0, 34, 0, MODE_EMA, PRICE_HIGH, pattern_indexies[0][1])) && (upper_pivot_price > iMA(NULL, 0, 89, 0, MODE_EMA, PRICE_CLOSE, pattern_indexies[0][1])) && is_trade_time && !have_buy_order) {
      open_price = NormalizeDouble(upper_pivot_price + spread_price + extra_price, Digits);
      stop_loss_price = NormalizeDouble(Low[pattern_indexies[0][2]] - extra_price, Digits);
      take_profit_price = NormalizeDouble(open_price + (open_price - stop_loss_price) / risk_to_reward_ratio, Digits);
      ticket = OrderSend(Symbol(), OP_BUYSTOP, 0.01, open_price, 0, stop_loss_price, take_profit_price, NULL, magic_number);
      if (ticket < 0)
        Alert("Error: OrderSend!");
    }
    if ((lower_pivot_price < Low[iLowest(NULL, 0, pattern_indexies[1][1], 0)]) && (lower_pivot_price < iMA(NULL, 0, 34, 0, MODE_EMA, PRICE_LOW, pattern_indexies[1][1])) && (lower_pivot_price < iMA(NULL, 0, 89, 0, MODE_EMA, PRICE_CLOSE, pattern_indexies[1][1])) && is_trade_time && !have_sell_order) {
      open_price = NormalizeDouble(lower_pivot_price - extra_price, Digits);
      stop_loss_price = NormalizeDouble(High[pattern_indexies[1][2]] + spread_price + extra_price, Digits);
      take_profit_price = NormalizeDouble(open_price - (stop_loss_price - open_price) / risk_to_reward_ratio + spread_price, Digits);
      ticket = OrderSend(Symbol(), OP_SELLSTOP, 0.01, open_price, 0, stop_loss_price, take_profit_price, NULL, magic_number);
      if (ticket < 0)
        Alert("Error: OrderSend!");
    }
  }
  return(0);
}

