コード例 #1
0
    def set_readonly_props(self) -> None:
        if not self._transactions:
            return

        self._start_capital = self._capital.get(
            ModelUtils.get_first_key(self._capital))
        self._end_capital = self._capital.get(
            ModelUtils.get_last_key(self._capital))
        self._hold_length_days_stats = StatUtils.get_descriptive_stats(
            [t.hold_length_days for t in self._transactions])
        self._change_in_capital_stats = StatUtils.get_descriptive_stats(
            [t.change_in_capital for t in self._transactions])
        self._has_profit_stats = StatUtils.get_descriptive_stats(
            [NumberUtils.to_int(t.has_profit) for t in self._transactions])
        self._pct_return = NumberUtils.get_change(self._end_capital,
                                                  self._start_capital)

        self._best_transactions = [
            t for t in sorted(self._transactions,
                              key=lambda x: x.change_in_capital,
                              reverse=True) if t.has_profit
        ][:20]
        self._worst_transactions = [
            t for t in sorted(self._transactions,
                              key=lambda x: x.change_in_capital)
            if not t.has_profit
        ][:20]

        symbol_grouped: Dict = {}
        for t in self._transactions:
            if not t.symbol_master.symbol in symbol_grouped:
                symbol_grouped[t.symbol_master.symbol]: Dict = {
                    'symbol_master': t.symbol_master,
                    'change_in_capital': 0,
                    'no_of_transactions': 0
                }
            symbol_grouped[t.symbol_master.
                           symbol]['change_in_capital'] += t.change_in_capital
            symbol_grouped[t.symbol_master.symbol]['no_of_transactions'] += 1

        symbol_grouped_list: List[BackTestResultItemPerSymbol] = []
        for k, v in symbol_grouped.items():
            item: BackTestResultItemPerSymbol = BackTestResultItemPerSymbol()
            item.symbol_master = symbol_grouped[k]['symbol_master']
            item.change_in_capital = NumberUtils.round(
                symbol_grouped[k]['change_in_capital'])
            item.no_of_transactions = symbol_grouped[k]['no_of_transactions']
            symbol_grouped_list.append(item)
        self._best_symbols = [
            i for i in sorted(symbol_grouped_list,
                              key=lambda x: x.change_in_capital,
                              reverse=True) if i.change_in_capital > 0
        ][:20]
        self._worst_symbols = [
            i for i in sorted(symbol_grouped_list,
                              key=lambda x: x.change_in_capital)
            if i.change_in_capital < 0
        ][:20]
コード例 #2
0
    def append_exponential_smoothing_max_min(
            self, prices: DataFrame, index: Any,
            exponential_smoothing_max_min_diff: float) -> DataFrame:

        if not (isinstance(prices, DataFrame)
                and AppConsts.PRICE_COL_SYMBOL_ID in prices.index.names
                and AppConsts.PRICE_COL_DATE in prices.index.names
                and AppConsts.CUSTOM_COL_EXPONENTIAL_SMOOTHING_PRICE
                in prices.columns
                and AppConsts.CUSTOM_COL_EXPONENTIAL_SMOOTHING_PRICE_PREV
                in prices.columns
                and AppConsts.CUSTOM_COL_EXPONENTIAL_SMOOTHING_PRICE_NEXT
                in prices.columns):
            return None
        if not AppConsts.CUSTOM_COL_EXPONENTIAL_SMOOTHING_MAX in prices.columns:
            prices[AppConsts.CUSTOM_COL_EXPONENTIAL_SMOOTHING_MAX] = 0
        if not AppConsts.CUSTOM_COL_EXPONENTIAL_SMOOTHING_MIN in prices.columns:
            prices[AppConsts.CUSTOM_COL_EXPONENTIAL_SMOOTHING_MIN] = 0

        curr_exp_smoothed_maxmin: float = 0.1
        for i, row in prices.loc[index].iterrows():
            symbol_id: int = i[0]
            curr_date: date = i[1]
            curr_exp_smoothed_p: float = row[
                AppConsts.CUSTOM_COL_EXPONENTIAL_SMOOTHING_PRICE]
            prev_exp_smoothed_p: float = row[
                AppConsts.CUSTOM_COL_EXPONENTIAL_SMOOTHING_PRICE_PREV]
            next_exp_smoothed_p: float = row[
                AppConsts.CUSTOM_COL_EXPONENTIAL_SMOOTHING_PRICE_NEXT]
            maxmin_diff: float = NumberUtils.get_change(
                curr_exp_smoothed_p, curr_exp_smoothed_maxmin)
            is_max: bool = (
                not np.isnan(prev_exp_smoothed_p)
                and not prev_exp_smoothed_p == 0
                and not np.isnan(next_exp_smoothed_p)
                and not next_exp_smoothed_p == 0 and maxmin_diff is not None
                and curr_exp_smoothed_p > prev_exp_smoothed_p
                and curr_exp_smoothed_p >= next_exp_smoothed_p
                and abs(maxmin_diff) > exponential_smoothing_max_min_diff)
            is_min: bool = (
                not np.isnan(prev_exp_smoothed_p)
                and not prev_exp_smoothed_p == 0
                and not np.isnan(next_exp_smoothed_p)
                and not next_exp_smoothed_p == 0 and maxmin_diff is not None
                and curr_exp_smoothed_p < prev_exp_smoothed_p
                and curr_exp_smoothed_p <= next_exp_smoothed_p
                and abs(maxmin_diff) > exponential_smoothing_max_min_diff)
            prices[AppConsts.CUSTOM_COL_EXPONENTIAL_SMOOTHING_MAX].loc[
                symbol_id, curr_date] = 1 if is_max else 0
            prices[AppConsts.CUSTOM_COL_EXPONENTIAL_SMOOTHING_MIN].loc[
                symbol_id, curr_date] = 1 if is_min else 0
            if is_max or is_min:
                curr_exp_smoothed_maxmin = curr_exp_smoothed_p
        return prices
コード例 #3
0
    def append_double_tops(self, prices: DataFrame, index: Any,
                           price_column: str, smooth_price_column: str,
                           max_column: str, min_column: str,
                           double_tops_diff: float) -> DataFrame:

        if not (isinstance(prices, DataFrame)
                and AppConsts.PRICE_COL_SYMBOL_ID in prices.index.names
                and AppConsts.PRICE_COL_DATE in prices.index.names
                and price_column in prices.columns and smooth_price_column
                in prices.columns and max_column in prices.columns
                and min_column in prices.columns):
            return None
        if not AppConsts.CUSTOM_COL_DOUBLE_TOPS in prices.columns:
            prices[AppConsts.CUSTOM_COL_DOUBLE_TOPS] = 0
        if not AppConsts.CUSTOM_COL_DOUBLE_TOPS_TARGET_PRICE in prices.columns:
            prices[AppConsts.CUSTOM_COL_DOUBLE_TOPS_TARGET_PRICE] = 0
        if not AppConsts.CUSTOM_COL_DOUBLE_TOPS_STOP_LOSS in prices.columns:
            prices[AppConsts.CUSTOM_COL_DOUBLE_TOPS_STOP_LOSS] = 0

        last_four_maxmins: List[float] = []
        for i, row in prices.loc[index].iterrows():
            symbol_id: int = i[0]
            curr_date: date = i[1]
            is_max: bool = row[max_column] == 1
            is_min: bool = row[min_column] == 1
            if is_max or is_min:
                if len(last_four_maxmins) >= 4:
                    last_four_maxmins.pop(0)
                last_four_maxmins.append(row[smooth_price_column])

            if len(last_four_maxmins) < 4:
                continue
            (point_a, point_b, point_c, point_d) = last_four_maxmins
            point_b_d_diff: float = NumberUtils.get_change(point_b, point_d)
            target_price: float = point_c - (point_d - point_c)
            has_double_tops: bool = (point_a < point_b and point_a < point_c
                                     and point_a < point_d
                                     and point_b > point_c
                                     and point_c < point_d
                                     and abs(point_b_d_diff) < double_tops_diff
                                     and row[price_column] < point_c)

            # and row[price_column] > target_price) # Actual Double Tops condition, but get better results without it.
            if has_double_tops:
                prices[AppConsts.CUSTOM_COL_DOUBLE_TOPS].loc[symbol_id,
                                                             curr_date] = 1
                prices[AppConsts.CUSTOM_COL_DOUBLE_TOPS_TARGET_PRICE].loc[
                    symbol_id, curr_date] = target_price
                prices[AppConsts.CUSTOM_COL_DOUBLE_TOPS_STOP_LOSS].loc[
                    symbol_id, curr_date] = point_d

        return prices
コード例 #4
0
    def append_inverted_head_and_shoulders(self, prices: DataFrame, index: Any,
                                           price_column: str,
                                           smooth_price_column: str,
                                           max_column: str, min_column: str,
                                           shoulder_diff: float,
                                           neck_diff: float) -> DataFrame:

        if not (isinstance(prices, DataFrame)
                and AppConsts.PRICE_COL_SYMBOL_ID in prices.index.names
                and AppConsts.PRICE_COL_DATE in prices.index.names
                and price_column in prices.columns and smooth_price_column
                in prices.columns and max_column in prices.columns
                and min_column in prices.columns):
            return None
        if not AppConsts.CUSTOM_COL_INVERTED_HEAD_AND_SHOULDERS in prices.columns:
            prices[AppConsts.CUSTOM_COL_INVERTED_HEAD_AND_SHOULDERS] = 0
        if not AppConsts.CUSTOM_COL_INVERTED_HEAD_AND_SHOULDERS_TARGET_PRICE in prices.columns:
            prices[AppConsts.
                   CUSTOM_COL_INVERTED_HEAD_AND_SHOULDERS_TARGET_PRICE] = 0
        if not AppConsts.CUSTOM_COL_INVERTED_HEAD_AND_SHOULDERS_STOP_LOSS in prices.columns:
            prices[
                AppConsts.CUSTOM_COL_INVERTED_HEAD_AND_SHOULDERS_STOP_LOSS] = 0

        last_six_maxmins: List[float] = []
        for i, row in prices.loc[index].iterrows():
            symbol_id: int = i[0]
            curr_date: date = i[1]
            is_max: bool = row[max_column] == 1
            is_min: bool = row[min_column] == 1
            if is_max or is_min:
                if len(last_six_maxmins) >= 6:
                    last_six_maxmins.pop(0)
                last_six_maxmins.append(row[smooth_price_column])

            if len(last_six_maxmins) < 6:
                continue
            (point_a, point_b, point_c, point_d, point_e,
             point_f) = last_six_maxmins
            point_b_f_diff: float = NumberUtils.get_change(point_b, point_f)
            point_c_e_diff: float = NumberUtils.get_change(point_c, point_e)
            neck_point: float = point_c if point_c > point_e else point_e
            target_price: float = neck_point + (neck_point - point_d)
            has_inverted_head_and_shoulders: bool = (
                point_a > point_b and point_a > point_c and point_a > point_d
                and point_a > point_e and point_a > point_f
                and point_b < point_c and point_b > point_d
                and point_b < point_e and point_c > point_d
                and point_c > point_f and point_d < point_e
                and point_d < point_f and abs(point_b_f_diff) < shoulder_diff
                and abs(point_c_e_diff) < neck_point
                and row[price_column] > neck_point
                and row[price_column] < target_price)
            if has_inverted_head_and_shoulders:
                prices[AppConsts.CUSTOM_COL_INVERTED_HEAD_AND_SHOULDERS].loc[
                    symbol_id, curr_date] = 1
                prices[
                    AppConsts.
                    CUSTOM_COL_INVERTED_HEAD_AND_SHOULDERS_TARGET_PRICE].loc[
                        symbol_id, curr_date] = target_price
                prices[AppConsts.
                       CUSTOM_COL_INVERTED_HEAD_AND_SHOULDERS_STOP_LOSS].loc[
                           symbol_id, curr_date] = point_f
        return prices