def reset_prd_var(dip=False):
     if not dip:
         self.cur_hgst_p = 0
         self.prd_start = None
     else:
         self.cur_hgst_p = self.sec_hgst_p
         self.prd_start = dt_to_str(dt)
     self.cur_lwst_p, self.sec_hgst_p = 100000000, 0
        def lst_prd_append(dip=False):

            dict_prd = {"count": prd_count, "start": self.prd_start,
                        "end": dt_to_str(dt)}
            if not dip:
                dict_prd['type'] = "R"
            else:
                dict_prd['type'] = "D"

            self.lst_prd.append(dict_prd)
 def get_dates(date):
     date1 = dt_to_str(str_to_dt(date) - timedelta(line_length))
     date2 = dt_to_str(str_to_dt(date) + timedelta(line_length))
     return date1, date2
    def get_trades(self, aut_stp_pct, sell_pct, sec_sell, hld_days):
        def reset_trading_var():
            self.ent_trggerd, self.in_trade = False, False
            self.ent_dt, self.sell_trggerd = None, False
            self.brk_tke_hg, self.aut_stp, self.ent_p = 0, 0, 0
            self.stp_loss, self.pre_ent_stp, self.hgst_brk_res_p = 0, 0, 0
            self.hld_days_lft = 0

        def add_trades(exit_p, use_prev_dt=False):
            self.rsult_p = n_decim(exit_p - self.ent_p)
            self.rsult_pct = n_decim((exit_p - self.ent_p) / self.ent_p * 100)
            self.arr_rsult_p = np.append(self.arr_rsult_p, self.rsult_p)
            self.arr_rsult_pct = np.append(self.arr_rsult_pct, self.rsult_pct)
            if not use_prev_dt:
                exit_dt = sdt
            else:
                exit_dt = prev_day_dt
            lst_trades.append((self.rsult_p, self.rsult_pct, self.ent_dt,
                               n_decim(self.ent_p), exit_dt, n_decim(exit_p)))

        def pct_change(p1, p2):
            return 1 - ((p1 - p2) / p1)

        def qualify_trigger(initial=True):
            lwr_res_stop, lwr_res_p = 0, 0

            for res_stats in sorted(self.dict_res_stats[prd_count]):
                (res_p, _, res_stop, res_take) = res_stats

                if res_p > cl:

                    if cl > self.pre_ent_stp and res_p - cl > cl - lwr_res_p:
                        self.pre_ent_stp = lwr_res_stop

                        if initial:
                            self.ent_trggerd = True
                            self.hld_days_lft = hld_days

                    elif not initial:
                        reset_trading_var()

                    break

                else:
                    lwr_res_stop = res_stop
                    lwr_res_p = res_p

        aut_stp_pct = num_to_pct(aut_stp_pct)
        sell_pct = num_to_pct(sell_pct)
        sec_sell = num_to_pct(sec_sell)
        self.hld_days = hld_days

        self.dict_trades = {}
        dict_triggers_copy = copy.deepcopy(self.dict_triggers)
        self.arr_rsult_p, self.arr_rsult_pct = np.array([]), np.array([])

        for period in self.lst_prd:
            lst_trades = []
            prev_day_dt, prev_day_cl = None, 0
            (prd_count, prd_start, prd_end, prd_type) = period_info(period)
            reset_trading_var()

            six_months = datetime.timedelta(180)
            pre_period_start = dt_to_str(str_to_dt(prd_start) - six_months)

            for day in self.ohlc_table[pre_period_start:prd_end].itertuples():
                (dt, op, hg, lw, cl) = day
                sdt = dt_to_str(dt)
                enter_new_trade = not self.in_trade and self.ent_trggerd

                if enter_new_trade and dt >= str_to_dt(prd_start):

                    if self.hld_days_lft == 0:

                        if op > self.pre_ent_stp:
                            self.ent_dt = sdt
                            self.ent_p = op
                            self.in_trade = True
                            self.aut_stp = n_decim(op * aut_stp_pct)
                        else:
                            reset_trading_var()
                    else:
                        if cl > op and cl > prev_day_cl:
                            qualify_trigger(initial=False)
                            self.hld_days_lft -= 1
                        else:
                            reset_trading_var()
                else:
                    self.ent_trggerd = False
                    self.pre_ent_stp = 0

                if self.sell_trggerd:
                    add_trades(op)
                    reset_trading_var()

                if self.in_trade and sdt in self.lst_earnings_dt:
                    if np.busday_count(self.ent_dt, sdt) > 4:
                        add_trades(prev_day_cl, use_prev_dt=True)

                    reset_trading_var()

                if self.in_trade:
                    higher_res_p, higher_res_take = 0, 0

                    for (res_p, *_) in self.dict_res_stats[prd_count]:

                        if cl > res_p:

                            if res_p > self.hgst_brk_res_p:
                                self.hgst_brk_res_p = res_p
                                self.brk_tke_hg = 0
                            break

                    for res_stats in self.dict_res_stats[prd_count]:
                        (res_p, _, res_stop, res_take) = res_stats
                        same_zone = res_p == self.hgst_brk_res_p

                        if res_stop < op and op < res_p and same_zone:

                            if hg > higher_res_take and pct_change(hg, cl) < sell_pct or\
                                    hg > higher_res_p and pct_change(hg, cl) < sec_sell:

                                if cl < higher_res_p:
                                    self.sell_trggerd = True

                            self.stp_loss = res_stop
                            break

                        elif res_p < op:

                            if hg > higher_res_p:

                                if cl < higher_res_p:

                                    if pct_change(hg, cl) < sec_sell:

                                        self.sell_trggerd = True
                                        self.brk_tke_hg = 0

                            if hg > higher_res_take:

                                if cl < higher_res_p:

                                    if hg > self.brk_tke_hg:
                                        self.brk_tke_hg = hg

                                    if pct_change(hg, cl) < sell_pct:

                                        self.sell_trggerd = True
                                        self.brk_tke_hg = 0

                            if self.brk_tke_hg:

                                if pct_change(self.brk_tke_hg, cl) < sell_pct:

                                    if cl < higher_res_p:
                                        self.sell_trggerd = True
                                        self.brk_tke_hg = 0

                            self.stp_loss = res_stop
                            break

                        higher_res_p = res_p
                        higher_res_take = res_take

                    if self.stp_loss > self.aut_stp:

                        if lw < self.stp_loss:

                            if op > self.stp_loss:
                                add_trades(self.stp_loss)
                            else:
                                add_trades(op)

                            reset_trading_var()
                    else:

                        if self.in_trade and lw < self.aut_stp:

                            if op >= self.aut_stp:
                                add_trades(self.aut_stp)
                            else:
                                add_trades(op)

                            reset_trading_var()

                prev_day_dt = sdt
                prev_day_cl = cl

                for trigger in dict_triggers_copy[prd_count].copy():
                    (trg_dt, trg_p, trg_start_dt, trg_end_dt) = trigger

                    if cl > trg_p and dt > trg_start_dt or dt > trg_end_dt:
                        dict_triggers_copy[prd_count].remove(trigger)

                    if self.in_trade or self.ent_trggerd:
                        continue

                    if cl > trg_p and dt == trg_end_dt:
                        qualify_trigger()

            previous_day_loss = False

            breakout_day = True
            after_prd_end = str_to_dt(prd_end) + six_months

            if self.in_trade:

                for day in self.ohlc_table[prd_end:after_prd_end].itertuples():
                    (dt, op, hg, lw, cl) = day
                    hgst_stp = n_decim(self.dict_res_stats[prd_count][0][2])
                    self.stp_loss = hgst_stp

                    if cl < self.stp_loss and not breakout_day:
                        add_trades(self.stp_loss)
                        break

                    if previous_day_loss:

                        if cl < op:
                            add_trades(cl)
                            break

                        if cl > op:
                            previous_day_loss = False

                    if cl < op:
                        previous_day_loss = True

                    breakout_day = False

            self.dict_trades[prd_count] = lst_trades
 def lst_trg_add():
     return dt_to_str(pot_dt1), pot_p1, pot_dt2, pot_inv_dt1
    def get_triggers(self, days_apart, inv_days, hld_bef,
                     hld_aft, hg_diff):
        def lst_trg_add():
            return dt_to_str(pot_dt1), pot_p1, pot_dt2, pot_inv_dt1

        self.dict_triggers = {}
        inv_dt = datetime.timedelta(inv_days)
        six_months = datetime.timedelta(180)

        hg_diff = hg_diff / 100
        total_hld = hld_bef + hld_aft + 1
        peak_i = hld_bef

        for period in self.lst_prd:
            prev_days_cl, prev_days_dt, lst_pot_trg, lst_trg = [], [], [], []
            (prd_count, prd_start, prd_end, prd_type) = period_info(period)

            pre_period_start = dt_to_str(str_to_dt(prd_start) - six_months)
            selected_period = self.ohlc_table[pre_period_start:prd_end]

            for day in selected_period.itertuples():
                (dt, op, hg, lw, cl) = day

                if len(prev_days_cl) > total_hld:
                    del prev_days_cl[0]
                    del prev_days_dt[0]

                    if hg_lw_finder(peak_i, prev_days_cl):
                        hg_dt = prev_days_dt[peak_i]
                        hg_cl = prev_days_cl[peak_i]
                        lst_pot_trg.append([hg_dt, hg_cl, hg_dt + inv_dt])

                prev_days_cl.append(cl)
                prev_days_dt.append(dt)

                for pot_trigger in lst_pot_trg:
                    (_, pot_trg_p, pot_inv_dt) = pot_trigger

                    if cl > pot_trg_p and dt < pot_inv_dt:
                        pot_trigger[2] = dt

            for index, pot_trg1 in enumerate(lst_pot_trg.copy()):
                (pot_dt1, pot_p1, pot_inv_dt1) = pot_trg1

                for pot_trg2 in lst_pot_trg[index+1:].copy():
                    (pot_dt2, pot_p2, _) = pot_trg2
                    trg_pct_diff = (pot_p1 - pot_p2) / pot_p1

                    if pot_inv_dt1 >= pot_dt2 and np.busday_count(dt_to_str(
                            pot_dt1), dt_to_str(pot_dt2)) > days_apart and\
                            trg_pct_diff <= hg_diff and trg_pct_diff >= 0:

                        if len(lst_trg) > 0:
                            added_to_list = False

                            for index2, (trg_dt, *_) in enumerate(lst_trg):

                                if pot_dt1 < str_to_dt(trg_dt):
                                    pot_dt1 = dt_to_str(pot_dt1)
                                    lst_trg.insert(index2, lst_trg_add())
                                    added_to_list = True
                                    break

                            if not added_to_list:
                                lst_trg.append(lst_trg_add())

                        else:
                            lst_trg.append(lst_trg_add())
                        break

            self.dict_triggers[prd_count] = sorted(lst_trg)
    def get_periods(self, pct_drop, sec_drop, only_rec):

        def reset_prd_var(dip=False):
            if not dip:
                self.cur_hgst_p = 0
                self.prd_start = None
            else:
                self.cur_hgst_p = self.sec_hgst_p
                self.prd_start = dt_to_str(dt)
            self.cur_lwst_p, self.sec_hgst_p = 100000000, 0

        def test_pre_prd(years=10):

            test_dt = str(int(self.prd_start[:4]) - years)
            return self.ohlc_table[test_dt]

        def lst_prd_append(dip=False):

            dict_prd = {"count": prd_count, "start": self.prd_start,
                        "end": dt_to_str(dt)}
            if not dip:
                dict_prd['type'] = "R"
            else:
                dict_prd['type'] = "D"

            self.lst_prd.append(dict_prd)

        def dict_prd_stats_add():

            self.dict_prd_stats[prd_count] = (self.cur_hgst_p, self.cur_lwst_p)

        pct_drop = num_to_pct(pct_drop)
        sec_drop = num_to_pct(sec_drop)

        reset_prd_var()
        prd_count = 1
        self.lst_prd, self.dict_prd_stats = [], {}

        for day in self.ohlc_table.itertuples():
            (dt, op, hg, lw, cl) = day

            if not self.prd_start:
                if cl > self.cur_hgst_p:
                    self.cur_hgst_p = cl

                if cl < (self.cur_hgst_p * pct_drop):
                    self.prd_start = dt_to_str(dt)
            else:
                if cl > self.cur_hgst_p:
                    try:
                        test_pre_prd()

                    except KeyError:
                        reset_prd_var()
                        continue

                    lst_prd_append()
                    dict_prd_stats_add()
                    reset_prd_var()
                    prd_count += 1
                    continue

                if cl < self.cur_lwst_p:
                    self.cur_lwst_p = cl

                if not only_rec:

                    if cl > (self.cur_lwst_p * 1.5) and cl > self.sec_hgst_p:
                        self.sec_hgst_p = cl

                    if self.sec_hgst_p and cl < (self.sec_hgst_p * sec_drop):
                        try:
                            test_pre_prd()

                        except KeyError:
                            reset_prd_var(dip=True)
                            continue

                        lst_prd_append(dip=True)
                        dict_prd_stats_add()
                        reset_prd_var(dip=True)
                        prd_count += 1