Пример #1
0
    def get_portfolio_vector(self, obs, index=-1):
        """
        Calculate portfolio vector from observation
        :param obs: pandas DataFrame: Observation
        :param index: int: Index to vector retrieve. -1 = last
        :return: numpy array: Portfolio vector with values ranging [0, 1] and norm 1
        """
        coin_val = {}
        for symbol in obs.columns.levels[0]:
            if symbol not in self.fiat:
                coin_val[symbol.split("_")[1]] = obs.at[obs.index[index], (symbol, symbol.split("_")[1])] * \
                                                 obs.at[obs.index[index], (symbol, 'open')]

        portval = 0
        for symbol in coin_val:
            portval += coin_val[symbol]
        portval += obs[self.fiat].iloc[index].values

        port_vec = np.zeros(obs.columns.levels[0].shape)
        for i, symbol in enumerate(coin_val):
            port_vec[i] = safe_div(coin_val[symbol], portval)

        port_vec[-1] = safe_div(obs[self.fiat].iloc[index].values, portval)

        return port_vec
Пример #2
0
def eir(obs, window, k):
    # polar returns
    # Find relation between price and previous price
    prices = obs.xs('open', level=1,
                    axis=1).astype(np.float64).iloc[-window - 1:]
    price_relative = np.hstack([
        np.mat(
            prices.rolling(2).apply(
                lambda x: safe_div(x[-2], x[-1]) - 1).dropna().values),
        np.zeros((window, 1))
    ])

    # Find the radius and the angle decomposition on price relative vectors
    radius = np.linalg.norm(price_relative, ord=1, axis=1)
    angle = np.divide(price_relative, np.mat(radius).T)

    # Select the 'window' greater values on the observation
    index = np.argpartition(radius,
                            -(int(window * k) + 1))[-(int(window * k) + 1):]
    index = index[np.argsort(radius[index])]

    # Return the radius and the angle for extreme found values
    R, Z = radius[index][::-1], angle[index][::-1]

    # alpha
    alpha = safe_div((radius.shape[0] - 1),
                     np.log(safe_div(radius[:-1], radius[-1])).sum())

    # gamma
    gamma = (1 / (Z.shape[0] - 1)) * np.power(
        np.clip(w * Z[:-1].T, 0.0, np.inf), alpha).sum()

    return gamma
Пример #3
0
    def make_report(self, env, obs, reward, episode_reward, t0, action_time,
                    next_action, prev_portval, init_portval):
        """
        Report generator
        :param env:
        :param obs:
        :param reward:
        :return:
        """

        # Portfolio values

        init_portval = float(init_portval)
        prev_portval = float(prev_portval)
        last_portval = float(env.calc_total_portval())

        # Returns summary
        msg = "\n>> Step {0}\nPortval: {1:.8f}\nStep Reward: {2:.6f}  [{3:.04f} %]\nCumulative Reward: {4:.6f}  [{5:.04f} %]\n".format(
            self.step, last_portval, reward, (np.exp(reward) - 1) * 100,
            episode_reward, (np.exp(episode_reward) - 1) * 100)

        msg += "\nStep portfolio change: %f" % (float(
            100 * safe_div(last_portval - prev_portval, prev_portval))) + " %"

        msg += "\nAccumulated portfolio change: %f" % (float(100 * safe_div(
            last_portval - init_portval, init_portval))) + " %\n"

        # Time summary
        msg += "\nLocal time: {0}\nTstamp: {1}\nLoop time: {2}\nUptime: {3}\n".format(
            datetime.now(), str(obs.index[-1]), action_time,
            str(pd.to_timedelta(time() - t0, unit='s')))

        # Prices summary
        msg += "\nPrices summary:\n"
        msg += "Pair       : Prev open:    Last price:     Pct change:\n"

        adm = 0.0
        k = 0
        for symbol in env.pairs:
            pp = obs.at[obs.index[-2], (symbol, 'open')]
            nep = obs.at[obs.index[-1], (symbol, 'close')]
            pc = 100 * safe_div((nep - pp), pp)
            adm += pc
            k += 1

            msg += "%-11s: %11.8f   %11.8f%11.2f" % (symbol, pp, nep,
                                                     pc) + " %\n"

        msg += "Mean change:                                %5.02f %%\n" % (
            adm / k)

        # Action summary
        msg += "\nAction Summary:\n"
        # Previous action
        try:
            pa = env.action_df.iloc[-3].astype(str).to_dict()
        except IndexError:
            pa = env.action_df.iloc[-1].astype(str).to_dict()

        # Currently Desired action
        try:
            da = env.action_df.iloc[-2].astype(str).to_dict()
        except IndexError:
            da = env.action_df.iloc[-1].astype(str).to_dict()

        # Last action
        la = env.action_df.iloc[-1].astype(str).to_dict()

        msg += "Symbol   : Previous:  Desired:   Executed:  Next:\n"
        for i, symbol in enumerate(pa):
            if symbol is not "online":
                pac = 100 * float(pa[symbol])
                dac = 100 * float(da[symbol])
                nac = 100 * float(la[symbol])
                na = 100 * float(next_action[i])

                msg += "%-8s:  %5.02f %%    %5.02f %%    %5.02f %%    %5.02f %%\n" % (
                    symbol, pac, dac, nac, na)
            else:
                msg += "%-8s:  %5s                 %5s\n" % (
                    symbol, pa[symbol], la[symbol])

        # Turnover
        try:
            ad = (env.action_df.iloc[-1].astype('f').values -
                  env.action_df.iloc[-3].astype('f').values)
        except IndexError:
            ad = (env.action_df.iloc[-1].astype('f').values -
                  env.action_df.iloc[-1].astype('f').values)

        tu = min(abs(np.clip(ad, 0.0, np.inf).sum()),
                 abs(np.clip(ad, -np.inf, 0.0).sum()))
        msg += "\nPortfolio Turnover: %.02f %%\n" % (tu * 100)

        # Slippage summary
        msg += "\nSlippage summary:\n"
        try:
            sl = (100 * (env.action_df.iloc[-1] - env.action_df.iloc[-2])).drop('online').astype('f').\
                describe(percentiles=[0.95, 0.05]).to_dict()
        except IndexError:
            sl = (100 * (env.action_df.iloc[-1] - env.action_df.iloc[-1])).drop('online').astype('f').\
                describe(percentiles=[0.95, 0.05]).to_dict()
        for symbol in sl:
            if symbol is not 'count':
                msg += "%-4s: %7.02f %%\n" % (str(symbol), sl[symbol])

        # Operational status summary
        msg += "\nStatus: %s\n" % str(env.status)

        # Strategy log summary
        for key in self.log:
            if isinstance(self.log[key], dict):
                msg += '\n' + str(key) + '\n'
                for subkey in self.log[key]:
                    msg += str(subkey) + ": " + str(
                        self.log[key][subkey]) + '\n'
            else:
                msg += '\n' + str(key) + ": " + str(self.log[key]) + '\n'

        return msg
Пример #4
0
def momentum(obs, period=14):
    prices = obs.xs('open', level=1, axis=1).astype(np.float64)
    # mean_volume = obs.xs('volume', level=1, axis=1).astype(np.float64).apply(lambda x: safe_div(x[-period:-1].sum(),
    #                                                                     x[-int(2 * period):-period].sum()), raw=True)
    mom = prices.apply(ta.MOM, timeperiod=period, raw=True).fillna(0.0)
    return 1 + safe_div(mom, prices.iloc[-period])  # * mean_volume
Пример #5
0
def ERI(R, Z, w):
    # alpha
    alpha = safe_div((R.shape[0] - 1), np.log(safe_div(R[:-1], R[-1])).sum())
    # gamma
    gamma = (1 / (Z.shape[0] - 1)) * np.power(np.clip(w * Z[:-1].T, 0.0, np.inf), alpha).sum()
    return gamma