Exemplo n.º 1
0
    def take_action(self,
                    action,
                    idx: int,
                    features: np.ndarray,
                    labels: np.ndarray,
                    targets: np.ndarray,
                    weights: np.ndarray = None,
                    gross_loss: np.ndarray = None) -> float:

        # skip the very first bar
        if idx <= 0:
            self.trade_log.rebalance(0)
            return 0

        # we use a n/fractions as target balance -> 10 shares 20,... shares, ...
        balance = action / self.trading_fraction * self.initial_capital
        self.trade_log.rebalance(balance)

        # new we need to evaluate the portfolio performance
        # where the targets are the prices
        prices = pd.Series(self.train[2][:idx+1].ravel(), name="prices")
        perf = self.trade_log.evaluate(prices, self.commission)
        self.current_net = perf["net"].iloc[-1]

        if self.stop_if_lost is not None and self.current_net < self.initial_capital * (1 - self.stop_if_lost):
            raise StopIteration(f"lost more then {self.stop_if_lost}%")

        return self.calculate_trade_reward(perf)
Exemplo n.º 2
0
def _default_returns_estimator(df, prices, expected_returns, return_period,
                               nr_of_assets):
    # return
    if expected_returns is None:
        exp_ret = df._[prices].pct_change().rolling(return_period).mean()
    elif isinstance(expected_returns, (int, float, np.ndarray)):
        exp_ret = pd.Series(np.ones(
            (len(df), nr_of_assets)) * expected_returns,
                            index=df.index)
    elif isinstance(expected_returns, str):
        exp_ret = df._[expected_returns]
    else:
        exp_ret = expected_returns

    return exp_ret.dropna()
Exemplo n.º 3
0
    def plot_classification(self, figsize=(16, 9)) -> Dict:
        import seaborn as sns
        import matplotlib.pyplot as plt
        from matplotlib import gridspec
        from pandas.plotting import register_matplotlib_converters

        # get rid of deprecation warning
        register_matplotlib_converters()

        probability_cutoff = self.probability_cutoff
        pc = self.probability_cutoff
        plots = {}

        for target in unique_level_columns(
                self.df) if self.df.columns.nlevels == 3 else [None]:
            # get target and frame
            df = self.df[target] if target is not None else self.df

            # define grid
            fig = plt.figure(figsize=figsize)
            gs = gridspec.GridSpec(2, 1, height_ratios=[1, 3])
            ax0 = plt.subplot(gs[0])
            ax1 = plt.subplot(gs[1])

            # plot probability
            bar = sns.lineplot(x=range(len(df)),
                               y=df[PREDICTION_COLUMN_NAME].iloc[:, 0],
                               ax=ax0)
            ax0.hlines(probability_cutoff,
                       0,
                       len(df),
                       color=sns.xkcd_rgb['silver'])

            # plot loss
            color = pd.Series(0, index=df.index)
            color.loc[(df[PREDICTION_COLUMN_NAME].iloc[:, 0] > pc)
                      & df[LABEL_COLUMN_NAME].iloc[:, 0] > pc] = 1
            color.loc[(df[PREDICTION_COLUMN_NAME].iloc[:, 0] <= pc)
                      & df[LABEL_COLUMN_NAME].iloc[:, 0] > pc] = 2

            colors = {
                0: sns.xkcd_rgb['white'],
                1: sns.xkcd_rgb['pale green'],
                2: sns.xkcd_rgb['cerise']
            }
            palette = [
                colors[color_index] for color_index in np.sort(color.unique())
            ]

            sns.scatterplot(ax=ax1,
                            x=range(len(df)),
                            y=df[GROSS_LOSS_COLUMN_NAME].iloc[:,
                                                              0].clip(upper=0),
                            size=df[GROSS_LOSS_COLUMN_NAME].iloc[:, 0] * -1,
                            hue=color,
                            palette=palette)

            plt.close()
            plots[target] = fig

        return plots
Exemplo n.º 4
0
def ta_markowitz(df: Typing.PatchedDataFrame,
                 covariances=None,
                 risk_aversion=5,
                 return_period=60,
                 prices='Close',
                 expected_returns=None,
                 rebalance_trigger=None,
                 solver='cvxopt',
                 tail=None):
    assert isinstance(df.columns, pd.MultiIndex), \
        "expect multi index columns 'prices', 'expected returns' and rebalance trigger"

    # risk
    if covariances is None:
        cov = ta_ewma_covariance(df._[prices])
    elif isinstance(covariances, str):
        cov = df._[covariances]
    else:
        cov = covariances
    cov = cov.dropna()

    # return
    exp_ret = _default_returns_estimator(df, prices, expected_returns,
                                         return_period, len(cov.columns))
    exp_ret.columns = cov.columns

    # re-balance
    trigger = (pd.Series(np.ones(len(df)), index=df.index) if
               rebalance_trigger is None else df[rebalance_trigger]).dropna()

    # non negative weight constraint and weights sum to 1
    h = np.zeros(len(cov.columns)).reshape((-1, 1))
    G = -np.eye(len(h))
    A = np.ones(len(h)).reshape((1, -1))
    b = np.ones(1)

    # magic solution's
    keep_solution = (np.empty(len(h)) * np.nan)
    uninvest = np.zeros(len(h))

    # keep last solution
    last_solution = None

    def optimize(t, sigma, pi):
        nonlocal last_solution
        nr_of_assets = len(sigma)

        # only optimize if we have a re-balance trigger (early exit)
        if last_solution is not None and last_solution.sum() > 0.99:
            # so we had at least one valid solution in the past
            # we can early exit if we do not have any signal or or no signal for any currently hold asset
            if t.ndim > 1 and t.shape[1] == nr_of_assets:
                if t[:, last_solution >= 0.01].sum().any() < 1:
                    return keep_solution
            else:
                if t.sum().any() < 1:
                    return keep_solution

        # make sure covariance matrix is positive definite
        simga = cov_nearest(sigma)

        # we perform optimization except when all expected returns are < 0
        # then we early exit with an un-invest command
        if len(pi[:, pi[0] < 0]) == pi.shape[1]:
            return uninvest
        else:
            try:
                sol = solve_qp(risk_aversion * sigma,
                               -pi.T,
                               G=G,
                               h=h,
                               A=A,
                               b=b,
                               solver=solver)
                if sol is None:
                    _log.error("no solution found")
                    return uninvest
                else:
                    return sol
            except Exception as e:
                _log.error(traceback.format_exc())
                return uninvest

    index = sorted(
        set(
            df.index.intersection(cov.index.get_level_values(0)).intersection(
                exp_ret.index).intersection(trigger.index)))
    if tail is not None:
        index = index[-abs(tail)]

    weights = [
        optimize(trigger.loc[[i]].values, cov.loc[[i]].values,
                 exp_ret[cov.columns].loc[[i]].values) for i in index
    ]

    # turn weights into a data frame
    return pd.DataFrame(weights, index=index, columns=cov.columns)