N = sortCoef.shape[0] / 10
longTickers = sortCoef.head(4*N).tail(3*N)[['ticker']].sort('ticker').reset_index(drop=True)
shortTickers = sortCoef.tail(4*N)[['ticker']].sort('ticker').reset_index(drop=True)
pfTickers = pd.concat((shortTickers[['ticker']], longTickers[['ticker']]), axis=0).sort('ticker').reset_index(drop=True)
# def getCovMatrix(tickers):

CarhartSample = CarhartDaily[(CarhartDaily['date'] >= START_TRAIN) &
                            (CarhartDaily['date'] <= END_TRAIN)][['Mkt-RF', 'SMB', 'HML', 'UMD']].reset_index(drop=True)
ResSample = Res[pfTickers.ticker]
FactorCov = np.cov(CarhartSample.as_matrix().transpose())
ResCov = np.cov(ResSample.as_matrix().transpose())
sens = Coef[['ticker', 'Mkt-RF', 'SMB', 'HML', 'UMD']].merge(pfTickers).sort('ticker').drop('ticker', axis=1).as_matrix()

totalCov = np.dot(np.dot(sens, FactorCov), sens.transpose()) + ResCov

wTickers = functions.pfOptimizer(longTickers, shortTickers, Coef, StockBeta, BETA_BOUND, WEIGHT_BOUND)
wTickers2 = wTickers[np.abs(wTickers['weight']) > 0.0005]
wTickers2['value'] = wTickers2['weight'] * CAPITAL
wTickers2.to_csv(r'%s/Portfolio_20141110_3.csv' % DataFolder, index=False)

iniPrices = pd.merge(StockPrices[StockPrices.date == BUILD_DATE][['ticker', 'date', 'adj_close']],
                     wTickers[['ticker']], on='ticker').reset_index(drop=True)
wCoef = Coef.merge(wTickers2).merge(StockBeta)

iniCoef = pd.DataFrame(np.dot(wCoef[['weight']].as_matrix().transpose(),
                              wCoef[['cqaBeta', 'Mkt-RF', 'SMB', 'HML', 'UMD']].as_matrix()))
iniCoef.columns = ['cqaBeta', 'beta', 'SMB', 'HML', 'UMD']

# Stocks with betas
# tmpData = Coef[['ticker', 'Mkt-RF', 'SMB', 'HML', 'UMD']].merge(pfTickers)
# groupBeta = pd.DataFrame()
Esempio n. 2
0
    betas = Coef.merge(tickers).rename(columns={'Mkt-RF': 'beta'})[[
        'ticker', 'beta'
    ]].reset_index(drop=True)
    sortCoef = betas.sort('beta').reset_index(drop=True)
    N = sortCoef.shape[0] / 10
    longTickers = sortCoef.head(4 * N).tail(
        3 * N)[['ticker']].sort('ticker').reset_index(drop=True)
    shortTickers = sortCoef.tail(
        3 * N)[['ticker']].sort('ticker').reset_index(drop=True)
    # shortTickersHigh = sortCoef.tail(3*N)[['ticker']].sort('ticker').reset_index(drop=True)
    # shortTickersLow = sortCoef.head(N)[['ticker']].sort('ticker').reset_index(drop=True)
    # mean_smb_40 = CarhartDaily[CarhartDaily['date'] <= start_date]['SMB'].tail(40).mean()
    # mean_smb_130 = CarhartDaily[CarhartDaily['date'] <= start_date]['SMB'].tail(130).mean()
    # diff_mean = mean_smb_40 - mean_smb_130
    try:
        wTickers = functions.pfOptimizer(longTickers, shortTickers, Coef,
                                         StockBeta, BETA_BOUND, WEIGHT_BOUND)
    except ValueError:
        value_error_count += 1
        pass
    wTickers = wTickers[(wTickers['weight'] >= 0.001) |
                        (wTickers['weight'] <= -0.001)]
    # test portfolio
    pfValues = pfValues.append(
        functions.testPortfolio2(StockPrices, SP500Prices, StockBeta, Coef,
                                 wTickers, total_value, sp500_value,
                                 start_date, end_date))
    total_value = pfValues['value'].iloc[-1]
    sp500_value = pfValues['SP500value'].iloc[-1]
pfValues.reset_index(drop=True)

def risk_return_expectation():
    back_date = datetime.datetime(2010, 11, 1)
    start_date = datetime.datetime(2013, 11, 1)
    end_date = datetime.datetime(2014, 10, 31)
    tickers = ReadData.ReadTickers(DataFolder)
    BETA_BOUND = 0.4
    WEIGHT_BOUND = 0.02
    decay = 0.003

    (Coef, Res) = functions.wReg(StockReturns, CarhartDaily, tickers, decay,
                                 back_date, start_date)
    betas = Coef.merge(tickers).rename(columns={'Mkt-RF': 'beta'})[[
        'ticker', 'beta'
    ]].reset_index(drop=True)
    sortCoef = betas.sort('beta').reset_index(drop=True)
    N = sortCoef.shape[0] / 10
    longTickers = sortCoef.head(4 * N).tail(
        3 * N)[['ticker']].sort('ticker').reset_index(drop=True)
    shortTickers = sortCoef.tail(
        3 * N)[['ticker']].sort('ticker').reset_index(drop=True)
    wTickers = functions.pfOptimizer(longTickers, shortTickers, Coef,
                                     StockBeta, BETA_BOUND, WEIGHT_BOUND)
    wTickers = wTickers[(wTickers['weight'] >= 0.001) |
                        (wTickers['weight'] <= -0.001)]
    total_value = 1e7
    sp500_value = 1e7

    # Initial Exposures
    Exposure = wTickers.merge(Coef)
    ini_beta = (Exposure['weight'] * Exposure['Mkt-RF']).sum()
    ini_smb = (Exposure['weight'] * Exposure['SMB']).sum()
    ini_hml = (Exposure['weight'] * Exposure['HML']).sum()
    ini_umd = (Exposure['weight'] * Exposure['UMD']).sum()
    print 'ini_beta = %.2f' % ini_beta
    print 'ini_smb = %.2f' % ini_smb
    print 'ini_hml = %.2f' % ini_hml
    print 'ini_umd = %.2f' % ini_umd

    # test portfolio
    pfValues = functions.testPortfolio2(
        StockPrices, SP500Prices, StockBeta, Coef, wTickers, total_value,
        sp500_value, start_date,
        end_date).rename(columns={'SP500value': 'sp500value'})
    pfValues['return'] = (pfValues['value'] - total_value) / total_value
    pfValues['sp500return'] = (pfValues['sp500value'] -
                               total_value) / total_value

    fig = plt.figure()
    ax = fig.add_subplot(1, 1, 1)
    matplotlib.rc('xtick', labelsize=36)
    matplotlib.rc('ytick', labelsize=36)
    plt.plot(pfValues['date'],
             pfValues['return'] * 100,
             color=cit_color,
             linewidth=6,
             label='Portfolio Value')
    plt.plot(pfValues['date'],
             pfValues['sp500return'] * 100,
             color='b',
             linewidth=6,
             label='S&P 500')
    plt.legend(loc=2, prop={'size': 36})
    fmt = '%.2f%%'  # Format you want the ticks, e.g. '40%'
    yticks = mtick.FormatStrFormatter(fmt)
    plt.xticks(rotation=25)
    ax.yaxis.set_major_formatter(yticks)
    plt.gcf().subplots_adjust(bottom=0.18)
    plt.grid()
    plt.show()

    breakpoints = [
        datetime.datetime(2013, 11, 30),
        datetime.datetime(2013, 12, 31),
        datetime.datetime(2014, 1, 31),
        datetime.datetime(2014, 2, 28),
        datetime.datetime(2014, 3, 31),
        datetime.datetime(2014, 4, 30),
        datetime.datetime(2014, 5, 31),
        datetime.datetime(2014, 6, 30),
        datetime.datetime(2014, 7, 31),
        datetime.datetime(2014, 8, 31),
        datetime.datetime(2014, 9, 30),
        datetime.datetime(2014, 10, 31),
    ]

    comparison = pd.DataFrame()
    tmp_start = datetime.datetime(2013, 10, 30)
    for tmp_end in breakpoints:
        print tmp_end
        tmp_pfValues = pfValues[(pfValues['date'] > tmp_start)
                                & (pfValues['date'] <= tmp_end)]
        # tmp_return = tmp_pfValues['return'].sum()
        # tmp_sp500_return = tmp_pfValues['sp500return'].sum()
        start_value = tmp_pfValues['value'].iloc[0]
        end_value = tmp_pfValues['value'].iloc[-1]
        tmp_return = ((end_value - start_value) / start_value) * 100
        start_sp500 = tmp_pfValues['sp500value'].iloc[0]
        end_sp500 = tmp_pfValues['sp500value'].iloc[-1]
        tmp_sp500_return = ((end_sp500 - start_sp500) / start_value) * 100
        comparison = comparison.append(
            pd.DataFrame([{
                'return': tmp_return,
                'sp500return': tmp_sp500_return
            }]))
        tmp_start = tmp_end

    comparison

    pfReturns = pfValues[['date', 'value', 'sp500value']]
    pfReturns['daily_return'] = (
        pfReturns['value'] -
        pfReturns['value'].shift(1)) / pfReturns['value'].shift(1)
    pfReturns['daily_sp500return'] = (
        pfReturns['sp500value'] -
        pfReturns['sp500value'].shift(1)) / pfReturns['value'].shift(1)
    pfReturns = pfReturns[1:]

    # Annualized volatility
    vol_portfolio = pfReturns['daily_return'].std() * math.sqrt(252)
    vol_sp500 = pfReturns['daily_sp500return'].std() * math.sqrt(252)
    n_days = np.float(pfReturns.shape[0])
    ave_return = ((pfValues['value'].iloc[-1] / pfValues['value'].iloc[0])**
                  (1 / n_days) - 1) * 100
    ave_sp500_return = (
        (pfValues['sp500value'].iloc[-1] / pfValues['sp500value'].iloc[0])**
        (1 / n_days) - 1) * 100
    cum_return = (pfValues['value'].iloc[-1] -
                  pfValues['value'].iloc[0]) / pfValues['value'].iloc[0] * 100
    cum_sp500return = (
        pfValues['sp500value'].iloc[-1] -
        pfValues['sp500value'].iloc[0]) / pfValues['sp500value'].iloc[0] * 100
    print 'cum_return = %.2f' % cum_return
    print 'cum_sp500return = %.2f' % cum_sp500return
    print 'vol_portfolio = %.4f' % vol_portfolio
    print 'vol_sp500 = %.4f' % vol_sp500

    sharpe_portfolio = pfReturns['daily_return'].mean() / vol_portfolio * 252
    sharpe_sp500 = pfReturns['daily_sp500return'].mean() / vol_sp500 * 252

    down_dev_portfolio = math.sqrt(
        pfReturns[pfReturns['daily_return'] < 0]['daily_return'].map(
            lambda x: x**2).sum() / n_days)
    down_dev_sp500 = math.sqrt(
        pfReturns[pfReturns['daily_sp500return'] < 0]['daily_sp500return'].map(
            lambda x: x**2).sum() / n_days)

    print 'down_dev_portfolio = %.4f' % down_dev_portfolio
    print 'down_dev_sp500 = %.4f' % down_dev_sp500

    max_drawdown = 0
    max_drawdown_sp500 = 0

    for i in range(pfValues.shape[0] - 1):
        for j in range(i + 1, pfValues.shape[0]):
            tmp_drawdown = (
                pfValues['value'].iloc[j] -
                pfValues['value'].iloc[i]) / pfValues['value'].iloc[i] * 100
            tmp_drawdown_sp500 = (pfValues['sp500value'].iloc[j] -
                                  pfValues['sp500value'].iloc[i]
                                  ) / pfValues['sp500value'].iloc[i] * 100
            max_drawdown = min(max_drawdown, tmp_drawdown)
            max_drawdown_sp500 = min(max_drawdown_sp500, tmp_drawdown_sp500)

    print 'max_drawdown = %.2f' % max_drawdown
    print 'max_drawdown_sp500 = %.2f' % max_drawdown_sp500

    pfReturns = pfReturns.merge(CarhartDaily, on='date')
    y = pfReturns['daily_return'] * 100 - pfReturns['RF']
    X = sm.add_constant(pfReturns[['Mkt-RF', 'SMB', 'HML', 'UMD']])
    model = sm.OLS(y, X).fit()
    print model.params
def risk_return_expectation():
    back_date = datetime.datetime(2010, 11, 1)
    start_date = datetime.datetime(2013, 11, 1)
    end_date = datetime.datetime(2014, 10, 31)
    tickers = ReadData.ReadTickers(DataFolder)
    BETA_BOUND = 0.4
    WEIGHT_BOUND = 0.02
    decay = 0.003

    (Coef, Res) = functions.wReg(StockReturns, CarhartDaily, tickers, decay, back_date, start_date)
    betas = Coef.merge(tickers).rename(columns={'Mkt-RF': 'beta'})[['ticker', 'beta']].reset_index(drop=True)
    sortCoef = betas.sort('beta').reset_index(drop=True)
    N = sortCoef.shape[0] / 10
    longTickers = sortCoef.head(4*N).tail(3*N)[['ticker']].sort('ticker').reset_index(drop=True)
    shortTickers = sortCoef.tail(3*N)[['ticker']].sort('ticker').reset_index(drop=True)
    wTickers = functions.pfOptimizer(longTickers, shortTickers,
                                                  Coef, StockBeta,
                                                  BETA_BOUND, WEIGHT_BOUND)
    wTickers = wTickers[(wTickers['weight'] >= 0.001) | (wTickers['weight'] <= -0.001)]
    total_value = 1e7
    sp500_value = 1e7

    # Initial Exposures
    Exposure = wTickers.merge(Coef)
    ini_beta = (Exposure['weight']*Exposure['Mkt-RF']).sum()
    ini_smb = (Exposure['weight']*Exposure['SMB']).sum()
    ini_hml = (Exposure['weight']*Exposure['HML']).sum()
    ini_umd = (Exposure['weight']*Exposure['UMD']).sum()
    print 'ini_beta = %.2f' % ini_beta
    print 'ini_smb = %.2f' % ini_smb
    print 'ini_hml = %.2f' % ini_hml
    print 'ini_umd = %.2f' % ini_umd

    # test portfolio
    pfValues = functions.testPortfolio2(StockPrices, SP500Prices, StockBeta, Coef, wTickers,
                                        total_value, sp500_value, start_date, end_date).rename(columns={'SP500value': 'sp500value'})
    pfValues['return'] = (pfValues['value']-total_value)/total_value
    pfValues['sp500return'] = (pfValues['sp500value']-total_value)/total_value

    fig = plt.figure()
    ax = fig.add_subplot(1,1,1)
    matplotlib.rc('xtick', labelsize=36)
    matplotlib.rc('ytick', labelsize=36)
    plt.plot(pfValues['date'], pfValues['return']*100, color=cit_color, linewidth=6,
             label='Portfolio Value')
    plt.plot(pfValues['date'], pfValues['sp500return']*100, color='b', linewidth=6,
             label='S&P 500')
    plt.legend(loc=2, prop={'size': 36})
    fmt = '%.2f%%' # Format you want the ticks, e.g. '40%'
    yticks = mtick.FormatStrFormatter(fmt)
    plt.xticks(rotation=25)
    ax.yaxis.set_major_formatter(yticks)
    plt.gcf().subplots_adjust(bottom=0.18)
    plt.grid()
    plt.show()

    breakpoints = [datetime.datetime(2013, 11, 30),
                   datetime.datetime(2013, 12, 31),
                   datetime.datetime(2014, 1, 31),
                   datetime.datetime(2014, 2, 28),
                   datetime.datetime(2014, 3, 31),
                   datetime.datetime(2014, 4, 30),
                   datetime.datetime(2014, 5, 31),
                   datetime.datetime(2014, 6, 30),
                   datetime.datetime(2014, 7, 31),
                   datetime.datetime(2014, 8, 31),
                   datetime.datetime(2014, 9, 30),
                   datetime.datetime(2014, 10, 31),
                   ]

    comparison = pd.DataFrame()
    tmp_start = datetime.datetime(2013, 10, 30)
    for tmp_end in breakpoints:
        print tmp_end
        tmp_pfValues = pfValues[(pfValues['date'] > tmp_start) &
                                (pfValues['date'] <= tmp_end)]
        # tmp_return = tmp_pfValues['return'].sum()
        # tmp_sp500_return = tmp_pfValues['sp500return'].sum()
        start_value = tmp_pfValues['value'].iloc[0]
        end_value = tmp_pfValues['value'].iloc[-1]
        tmp_return = ((end_value - start_value) / start_value) * 100
        start_sp500 = tmp_pfValues['sp500value'].iloc[0]
        end_sp500 = tmp_pfValues['sp500value'].iloc[-1]
        tmp_sp500_return = ((end_sp500 - start_sp500) / start_value) * 100
        comparison = comparison.append(pd.DataFrame([{'return': tmp_return,
                                                     'sp500return': tmp_sp500_return
                                                     }]))
        tmp_start = tmp_end

    comparison

    pfReturns = pfValues[['date', 'value', 'sp500value']]
    pfReturns['daily_return'] = (pfReturns['value']-pfReturns['value'].shift(1))/pfReturns['value'].shift(1)
    pfReturns['daily_sp500return'] = (pfReturns['sp500value']-pfReturns['sp500value'].shift(1))/pfReturns['value'].shift(1)
    pfReturns = pfReturns[1:]

    # Annualized volatility
    vol_portfolio = pfReturns['daily_return'].std()*math.sqrt(252)
    vol_sp500 = pfReturns['daily_sp500return'].std()*math.sqrt(252)
    n_days = np.float(pfReturns.shape[0])
    ave_return = ((pfValues['value'].iloc[-1]/pfValues['value'].iloc[0])**(1/n_days)-1)*100
    ave_sp500_return = ((pfValues['sp500value'].iloc[-1]/pfValues['sp500value'].iloc[0])**(1/n_days)-1)*100
    cum_return = (pfValues['value'].iloc[-1]-pfValues['value'].iloc[0])/pfValues['value'].iloc[0]*100
    cum_sp500return = (pfValues['sp500value'].iloc[-1]-pfValues['sp500value'].iloc[0])/pfValues['sp500value'].iloc[0]*100
    print 'cum_return = %.2f' % cum_return
    print 'cum_sp500return = %.2f' % cum_sp500return
    print 'vol_portfolio = %.4f' % vol_portfolio
    print 'vol_sp500 = %.4f' % vol_sp500

    sharpe_portfolio = pfReturns['daily_return'].mean()/vol_portfolio * 252
    sharpe_sp500 = pfReturns['daily_sp500return'].mean()/vol_sp500  * 252

    down_dev_portfolio = math.sqrt(pfReturns[pfReturns['daily_return']<0]['daily_return'].map(lambda x: x**2).sum()/n_days)
    down_dev_sp500 = math.sqrt(pfReturns[pfReturns['daily_sp500return']<0]['daily_sp500return'].map(lambda x: x**2).sum()/n_days)

    print 'down_dev_portfolio = %.4f' % down_dev_portfolio
    print 'down_dev_sp500 = %.4f' % down_dev_sp500

    max_drawdown = 0
    max_drawdown_sp500 = 0

    for i in range(pfValues.shape[0]-1):
        for j in range(i+1, pfValues.shape[0]):
            tmp_drawdown = (pfValues['value'].iloc[j]-pfValues['value'].iloc[i])/pfValues['value'].iloc[i]*100
            tmp_drawdown_sp500 = (pfValues['sp500value'].iloc[j]-pfValues['sp500value'].iloc[i])/pfValues['sp500value'].iloc[i]*100
            max_drawdown = min(max_drawdown, tmp_drawdown)
            max_drawdown_sp500 = min(max_drawdown_sp500, tmp_drawdown_sp500)

    print 'max_drawdown = %.2f' % max_drawdown
    print 'max_drawdown_sp500 = %.2f' % max_drawdown_sp500

    pfReturns = pfReturns.merge(CarhartDaily, on='date')
    y = pfReturns['daily_return'] * 100 - pfReturns['RF']
    X = sm.add_constant(pfReturns[['Mkt-RF', 'SMB', 'HML', 'UMD']])
    model = sm.OLS(y, X).fit()
    print model.params