def optimize(): market = Market() asset_returns = compute_market_returns(market) min_lower = -10 valid_portfolios = [] for i in range(0, 100): asset_weights = {} left = 1 for asset in market.get_assets(): weight = random() * left asset_weights[asset] = weight left = left - weight if left > 0: asset_weights[market.get_assets()[:1][0]] += left portfolio = Portfolio('Portfolio' + str(i), asset_weights) portfolio_returns = evaluate_portfolio(market, portfolio, asset_returns) if np.percentile(portfolio_returns, 25) > min_lower: valid_portfolios.append((portfolio, portfolio_returns)) valid_portfolios.sort(key=lambda p: np.mean(p[1]), reverse=True) best_portfolio = valid_portfolios[0] comparisons = [compute()] to_display = comparisons.append(best_portfolio) return to_display
def build_random_portfolio(): asset_count = random.randint(1, len(MARKET.assets)) new_portfolio_values = {} for asset in random.sample(MARKET.assets, asset_count): new_portfolio_values[asset] = random.random() portfolio = Portfolio(random_name(), adjust_weight(new_portfolio_values)) return portfolio
def add_random_asset(portfolio): new_portfolio_values = portfolio.asset_and_weights.copy() if len(new_portfolio_values) < len(MARKET.get_assets()): asset_to_add = random.choice( list(set(MARKET.get_assets()) - set(new_portfolio_values.keys()))) weight = random.random() new_portfolio_values[asset_to_add] = weight return Portfolio(random_name(), adjust_weight(new_portfolio_values))
def change_random_asset(portfolio): new_portfolio_values = portfolio.asset_and_weights.copy() asset_to_adjust = random.choice(list(portfolio.asset_and_weights.keys())) value_to_add = random.random() - 0.5 new_value = portfolio.weight(asset_to_adjust) + value_to_add if new_value <= 0: new_portfolio_values.pop(asset_to_adjust) else: new_portfolio_values[asset_to_adjust] = new_value return Portfolio(random_name(), adjust_weight(new_portfolio_values))
def test_evaluate_portfolio_return(self): single_asset_portfolio = Portfolio('US Stocks only', {MARKET.real_estate: 1}) portfolio_return = MARKET.evaluate_portfolio_return( single_asset_portfolio) self.assertAlmostEqual(portfolio_return.mean, MARKET.real_estate.mean, delta=0.5)
def crossover(first_portfolio, other_portfolio): new_portfolio_values = {} all_assets = set(first_portfolio.asset_and_weights.keys()).union( other_portfolio.asset_and_weights.keys()) for asset in all_assets: pick_from = first_portfolio if random.random( ) > 0.5 else other_portfolio if pick_from.weight(asset) > 0: new_portfolio_values[asset] = pick_from.weight(asset) if sum(new_portfolio_values.values()) == 0: new_portfolio_values[list(all_assets)[0]] = 1 return Portfolio(random_name(), adjust_weight(new_portfolio_values))
def test_portfolios(self): portfolio_0_100 = Portfolio('Pure Bond', { MARKET.eu_stocks: 0, MARKET.agg_bonds: 1, MARKET.gold: 0 }) portfolio_50_50 = Portfolio('50/50', { MARKET.eu_stocks: 0.5, MARKET.agg_bonds: 0.5, MARKET.gold: 0 }) portfolio_60_40 = Portfolio('60/40', { MARKET.eu_stocks: 0.6, MARKET.agg_bonds: 0.4, MARKET.gold: 0 }) portfolio_100_0 = Portfolio('Pure Equity', { MARKET.eu_stocks: 1, MARKET.agg_bonds: 0, MARKET.gold: 0 }) golden_butterfly = Portfolio('Golden Butterfly', { MARKET.eu_stocks: 0.4, MARKET.agg_bonds: 0.4, MARKET.gold: 0.2 }) varx = Portfolio( 'VarX', { MARKET.ch_stocks: 0.175, MARKET.us_stocks: 0.175, MARKET.eu_stocks: 0.20, MARKET.agg_bonds: 0.15, MARKET.real_estate: 0.05, MARKET.cash: 0.15, MARKET.gold: 0.1 }) varx_plus = Portfolio( 'VarX+', { MARKET.ch_stocks: 0.185, MARKET.us_stocks: 0.185, MARKET.eu_stocks: 0.20, MARKET.agg_bonds: 0.15, MARKET.real_estate: 0.05, MARKET.cash: 0.13, MARKET.gold: 0.10 }) current = Portfolio( 'current', { MARKET.ch_stocks: 0.055, MARKET.us_stocks: 0.12, MARKET.eu_stocks: 0.285, MARKET.agg_bonds: 0.105, MARKET.real_estate: 0.005, MARKET.cash: 0.375, MARKET.gold: 0.055 }) dalio_curr = Portfolio( 'Bridgewater', { MARKET.eu_stocks: 0.05, MARKET.ch_stocks: 0.3, MARKET.us_stocks: 0.4, MARKET.agg_bonds: 0.05, MARKET.gold: 0.2 }) portfolios = [ portfolio_0_100, portfolio_50_50, portfolio_60_40, portfolio_100_0, golden_butterfly, current, varx, varx_plus, dalio_curr ] for p in portfolios: print(MARKET.evaluate_portfolio_return(p))
def remove_random_asset(portfolio): new_portfolio_values = portfolio.asset_and_weights.copy() if len(portfolio.asset_and_weights.items()) > 1: removed_item = random.choice(list(portfolio.asset_and_weights.items())) new_portfolio_values.pop(removed_item[0]) return Portfolio(random_name(), adjust_weight(new_portfolio_values))
def compute(): market = Market() portfolio_0_100 = Portfolio('Pure Bond', { market.eu_stocks: 0, market.agg_bonds: 1, market.gold: 0 }) portfolio_50_50 = Portfolio('50/50', { market.eu_stocks: 0.5, market.agg_bonds: 0.5, market.gold: 0 }) portfolio_60_40 = Portfolio('60/40', { market.eu_stocks: 0.6, market.agg_bonds: 0.4, market.gold: 0 }) portfolio_100_0 = Portfolio('Pure Equity', { market.eu_stocks: 1, market.agg_bonds: 0, market.gold: 0 }) golden_butterfly = Portfolio('Golden Butterfly', { market.eu_stocks: 0.4, market.agg_bonds: 0.4, market.gold: 0.2 }) varx = Portfolio('VarX', { market.ch_stocks: 0.175, market.us_stocks: 0.175, market.eu_stocks: 0.20, market.agg_bonds: 0.15, market.real_estate: 0.05, market.cash: 0.15, market.gold: 0.1 }) current = Portfolio('current', { market.ch_stocks: 0.055, market.us_stocks: 0.12, market.eu_stocks: 0.285, market.agg_bonds: 0.105, market.real_estate: 0.005, market.cash: 0.375, market.gold: 0.055 }) dalio_curr = Portfolio('Bridgewater', { market.eu_stocks: 0.05, market.ch_stocks: 0.3, market.us_stocks: 0.4, market.agg_bonds: 0.05, market.gold: 0.2 }) portfolios = [portfolio_0_100, portfolio_50_50, portfolio_60_40, portfolio_100_0, golden_butterfly, current, varx, dalio_curr] asset_returns = compute_market_returns(market) all_returns = [evaluate_portfolio(market, p, asset_returns) for p in portfolios] fig = plt.figure() ax = fig.add_subplot() plt.yticks(range(-20, 20)[::2]) ax.grid(b=True, which='both', axis='y') ax.boxplot(all_returns, sym='') ax.set_xticklabels([p.name for p in portfolios]) plt.show() return zip(portfolios, all_returns)