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
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
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
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
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