Пример #1
0
    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]
Пример #2
0
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)
Пример #3
0
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()
Пример #4
0
 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
Пример #5
0
    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)
Пример #6
0
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))
Пример #7
0
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
Пример #8
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
Пример #9
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))
Пример #10
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:

        # 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))
Пример #11
0
 def test_calculate_sharpe_ratio(self):
     pnl = self.generate_pnl()
     returns = utils.calculate_returns(pnl)
     self.assertEqual(-2.5095619671562686,
                      backtester._calculate_sharpe_ratio(returns))