def step(self, current_return): """ Perturb policy weights by generating neighboring policies and comparing the return from each policy with current best. if the return from any of neighboring policy is greater than or equal to current best then we use that policy as our current. Parameters ---------- current_return (int): Return of current rollout """ super().step(current_return) # Check the return from all neighbors candidate_returns = [current_return] candidate_weights = [self.w] for _ in range(self.neighbors): policy = deepcopy(self) policy.w = self.best_weights + self.noise * np.random.rand(*self.best_weights.shape) rewards = run_episode(policy, self.env, self.max_steps) policy_return = calculate_returns(self.gamma, rewards) candidate_returns.append(policy_return) candidate_weights.append(policy.w) # Find the max return from candidate returns and # compare it with our best return best_idx = np.argmax(np.array(candidate_returns)) if candidate_returns[best_idx] >= self.best_return: self.best_return = candidate_returns[best_idx] self.best_weights = candidate_weights[best_idx] self.w = candidate_weights[best_idx]
def train(args, stop_on_solve=True, print_every=100): """ Create gym environment and train a variant of hill climbing policy """ env = gym.make(args.env) state_size = env.observation_space.shape[0] action_size = env.action_space.n # env_name, policy_name, num_episodes, max_steps, goal_score policy = load_policy(args.policy, env, args.steps, args.gamma) avg_return = deque(maxlen=100) all_rewards = [] for episode in range(1, args.episodes + 1): # rollout rewards = run_episode(policy, env, args.steps) # calculate discounted return current_return = calculate_returns(args.gamma, rewards) # update policy policy.step(current_return) # record returns avg_return.append(current_return) all_rewards.append(current_return) if episode % print_every == 0: logger.info('{}/{} average return of last 100 episodes {}'.format( episode, args.episodes, np.mean(avg_return))) if stop_on_solve: if np.mean(avg_return) >= args.goal: print('Env solved in {}'.format(episode)) break return policy, all_rewards, np.mean(avg_return)
def main(): start_price = 70.0 prices = utils.generate_gbm_prices(500, 70.0, 0.05, 0.3, 1.0) returns = (utils.calculate_returns(prices) + 1.0).cumprod() - 1.0 pnl = start_price * (returns + 1.0) max_dd, max_count, max_dd_idx, max_duration_idx, hwm_idx = \ utils.calculate_max_drawdown(returns) plt.plot(pnl) plt.plot((hwm_idx, max_dd_idx), (pnl[hwm_idx], pnl[max_dd_idx]), color='black') plt.annotate('max dd ({0:.2f}%)'.format(max_dd * 100.0), xy=(max_dd_idx, pnl[max_dd_idx]), xycoords='data', xytext=(0, -50), textcoords='offset points', arrowprops=dict(facecolor='black', shrink=0.05)) max_duration_start_idx = max_duration_idx - max_count max_duration_x1x2 = (max_duration_start_idx, max_duration_idx) max_duration_y1y2 = (pnl[max_duration_start_idx], pnl[max_duration_start_idx]) plt.plot(max_duration_x1x2, max_duration_y1y2, color='black') plt.annotate('max dd duration ({} days)'.format(max_count), xy=((max_duration_start_idx + max_duration_idx) / 2, pnl[max_duration_start_idx]), xycoords='data', xytext=(-100, 30), textcoords='offset points', arrowprops=dict(facecolor='black', shrink=0.05)) plt.show()
def run(self, np_close): self._validate_params() signals = self._run_strategy(np_close) positions = self._calculate_positions(np_close, signals) returns = utils.calculate_returns(positions) sharpe_ratio = _calculate_sharpe_ratio(returns) _print_results(np_close, positions, sharpe_ratio) return sharpe_ratio
def test_calculate_returns(self): positions = np.array( [0., 15., 15., 27.5, 27.5, 17.5, 32.5, 32.5, 10., -7.5]) returns = utils.calculate_returns(positions) np_utils.assert_allclose([ 0., 0., 0., 0.83333333, 0., -0.36363636, 0.85714286, 0., -0.69230769, -1.75 ], returns, rtol=1e-7)
def main(): futures_prices = load_futures_prices() n_futures = [30., 60., 90., 120., 150., 180.] prices = {} # start = '21/10/2004' # Going earlier then this date results in missing data, as we don't # have all required prices for all periods start = '01/01/2009' # end = '30/12/2011' end = '30/12/2014' dates = pd.date_range(start, end, normalize=True) prices = pd.DataFrame(index=dates) expected_nan = 0 for n in n_futures: result = load_vix_future(n, futures_prices, dates) if expected_nan is 0: expected_nan = np.count_nonzero(~np.isnan(result)) else: nan_count = np.count_nonzero(~np.isnan(result)) if expected_nan != nan_count: print('Different count of NaN values returned for period {}, ' 'expected: {}, actual: {}'.format( n, expected_nan, nan_count)) utils.np_print_full(result) exit(1) prices[str(n)] = result prices = prices.dropna() returns = pd.DataFrame(index=prices.index) for key in prices: returns[key] = utils.calculate_returns(prices[key]) prices.plot() plt.show() corr = returns.corr() print(corr) eig_val, eig_vec = np.linalg.eig(corr) prop_of_variation = eig_val / eig_val.sum() print(eig_val) print(eig_vec) print('Proportion of variation explained: {}'.format(prop_of_variation))
def main(): """Run main program.""" index = "dowjones" index = "frankfurt" parser = argparse.ArgumentParser(description="Parse arguments for models.") parser.add_argument( "--indir", help="Dataset directory.", default="../data/dowjones/all_stocks_2006-01-01_to_2018-01-01.csv") parser.add_argument('--outdir', help='Model directory.', default="../model/dowjones/sample.csv") # args = parser.parse_args() # dataset = pd.read_csv(args.indir, # index_col='Date', # parse_dates=['Date']) dataset = pd.read_csv(f"../data/frankfurt_calculated/stocks.csv", index_col='Date', parse_dates=['Date']) returns = calculate_returns(dataset) log_returns = calculate_log_returns(dataset) labels = calculate_class(returns) absolute_labels = calculate_absolute_class(returns) log_labels = calculate_class(log_returns) absolute_log_labels = calculate_absolute_class(log_returns) # returns = (returns - returns.mean()) / returns.std() print(f"Returns shape: {returns.shape}") print(f"Labels shape: {labels.shape}") returns.to_csv(f"../data/{index}_calculated/returns1.csv") labels.to_csv(f"../data/{index}_calculated/labels1.csv") absolute_labels.to_csv(f"../data/{index}_calculated/absolute_labels1.csv") log_returns.to_csv(f"../data/{index}_calculated/log_returns1.csv") log_labels.to_csv(f"../data/{index}_calculated/log_labels1.csv") absolute_log_labels.to_csv( f"../data/{index}_calculated/absolute_log_labels1.csv") print("Done.") return 0
def main(): """Run main program.""" start = time.time() parser = argparse.ArgumentParser( description="Parse arguments for models.") parser.add_argument( "--indir", help="Dataset directory.", default="../data/dowjones/all_stocks_2006-01-01_to_2018-01-01.csv") parser.add_argument('--outdir', help='Model directory.', default="../data/dowjones_calculated/rebalance.csv") args = parser.parse_args() dataset = pd.read_csv(args.indir, index_col='Date', parse_dates=['Date']) returns = calculate_returns(dataset) times = 1000 results = random_trading(returns, times=times) pd.DataFrame(data=results).to_csv( f"../data/dowjones_calculated/random_trading_{times}times.csv", sep=',', index=False, header=["No Rebalance", "Rebalance"]) print("Done.") end = time.time() print(end - start) return 0
def main(): run_date = dt.datetime(2014, 9, 19) run_date_str = run_date.strftime('%Y%m%d') # symbols = \ # data_loader.load_symbol_list( # '/Users/Conor/code/python/conor10.tickdata/symbols/' # 'SP500/20140907/symbols.txt') symbols = ['AAPL'] all_options_prices = data_loader.load_option_data( 'SP500', '/Users/Conor/code/python/conor10.tickdata/chains', symbols, start_date=run_date_str, end_date=run_date_str) all_stock_prices = data_loader.load_price_data( '/Users/Conor/code/python/conor10.tickdata/daily_prices/SP500', symbols) for symbol in symbols: stock_price = all_stock_prices[symbol] underlying_price = \ stock_price['Adj Close'][[run_date]].values[0] print(underlying_price) stock_price['Adj Returns'] = \ utils.calculate_returns(stock_price['Adj Close'].values) start_date = run_date - dt.timedelta(31) sigma = stock_price[start_date:run_date]['Adj Returns'].std( ) * math.sqrt(252.0) option_prices = all_options_prices[symbol] for capture_date in option_prices.keys(): expiries = option_prices[capture_date] for expiry in expiries.keys(): prices = expiries[expiry] puts = prices[OptionType.PUT] print(expiry) # print(puts) dt_expiry = dt.datetime.strptime(expiry, '%Y%m%d') days_in_year = 366 if calendar.isleap(dt_expiry.year) else 365 days_to_expiry = dt_expiry - run_date delta = days_to_expiry.days / days_in_year for strike in puts.index: last_price_str = puts.ix[strike]['LAST_PRICE'] if last_price_str == '-': continue last_price = float(last_price_str) price = option.calc_option_price(OptionType.PUT, strike, underlying_price, sigma, delta, risk_free_rate=0.01) implied_volatility = option.implied_volatility( OptionType.PUT, strike, underlying_price, last_price, delta) print('Strike: {}, calc price: {}, actual {}'.format( strike, price, last_price)) print('Sigma: {}, implied sigma: {}'.format( sigma, implied_volatility))
def main(): run_date = dt.datetime(2014, 9, 19) run_date_str = run_date.strftime('%Y%m%d') # symbols = \ # data_loader.load_symbol_list( # '/Users/Conor/code/python/conor10.tickdata/symbols/' # 'SP500/20140907/symbols.txt') symbols = ['AAPL'] all_options_prices = data_loader.load_option_data( 'SP500', '/Users/Conor/code/python/conor10.tickdata/chains', symbols, start_date=run_date_str, end_date=run_date_str) all_stock_prices = data_loader.load_price_data( '/Users/Conor/code/python/conor10.tickdata/daily_prices/SP500', symbols) for symbol in symbols: # Get all puts # if put is OTM, predict probability it will be ITM at expiry stock_prices = all_stock_prices[symbol] underlying_price = \ stock_prices['Close'][[run_date]].values[0] print(underlying_price) stock_prices['Adj Returns'] = \ utils.calculate_returns(stock_prices['Adj Close'].values) option_prices = all_options_prices[symbol] for capture_date in option_prices.keys(): expiries = option_prices[capture_date] for expiry in sorted(expiries.keys()): prices = expiries[expiry] puts = prices[OptionType.PUT] print(expiry) dt_expiry = dt.datetime.strptime(expiry, '%Y%m%d') # TODO: Calculate the exact value - # TODO: there's 9 trading holidays on NASDAQ in 2014 days_in_year = np.busday_count('2014', '2015') - 9 days_to_expiry = utils.work_day_count(run_date, dt_expiry) # TODO: Need to calculate trading days to expiry # TODO: workalendar may be useful #TODO Rename duration = days_to_expiry / days_in_year # TODO: Make model more sophisticated for sigma # lookback_period = days_to_expiry lookback_period = days_in_year sigma = calc_sigma(stock_prices, lookback_period, run_date, days_in_year) itm_probability = price_series.calc_itm_probability( puts.index, underlying_price, sigma, days_to_expiry, 10000, OptionType.PUT) # print(itm_probability) # We're only interested in strikes that are OTM to start with otm_probabilities = itm_probability[np.where( itm_probability[:, 0] < underlying_price)] # print(otm_probabilities) # select all options we have a last price for & assume this # selling cost results = [] for strike, probability in otm_probabilities: last_price_str = puts.ix[strike]['LAST_PRICE'] if last_price_str == '-': continue last_price = float(last_price_str) # print('Strike: {}, P(ITM): {}, Last Price: {}'.format( # strike, probability, last_price)) results.append([strike, probability, last_price]) data = np.asarray(results).T # last_price / probability upside_ratio = data[2] / data[1] # discard inf values upside_ratio[np.where(upside_ratio == np.inf)] = 0 upside_ratio[np.where(upside_ratio == np.nan)] = 0 optimal_idx = upside_ratio.argmax() # print('Optimal option: {}'.format(data[0][optimal_idx])) optimal = [[data[0][optimal_idx]], [data[1][optimal_idx]], [data[2][optimal_idx]]] plot3D( data[0], data[1], data[2], optimal, 'Date: {}, Underlying: {}, Last price: {}, Expiry: {}'. format(capture_date, symbol, underlying_price, expiry))
def test_calculate_sharpe_ratio(self): pnl = self.generate_pnl() returns = utils.calculate_returns(pnl) self.assertEqual(-2.5095619671562686, backtester._calculate_sharpe_ratio(returns))