def get_priceMom(rebalDate, codes): past = ut.get_recentBday(rebalDate - datetime.timedelta(365)) recent = ut.get_recentBday(rebalDate - datetime.timedelta(30)) rebalDate = ut.get_recentBday(rebalDate) prices = ut.get_stock_price(codes, past, rebalDate ) mom_12M = (prices.loc[rebalDate, :] / prices.loc[past, :]) - 1 mom_1M = (prices.loc[rebalDate, :] / prices.loc[recent, :]) - 1 momData = (mom_12M - mom_1M).dropna() return momData
def get_priceMom(codes, rebalDate): yearAgo = rebalDate - datetime.timedelta(days=365) monthAgo = rebalDate - datetime.timedelta(days=30) yearAgo = util.get_recentBday(yearAgo) monthAgo = util.get_recentBday(monthAgo) rebalDate = util.get_recentBday(rebalDate) prices = util.get_stock_price(codes, yearAgo, rebalDate) mom_12M = (prices.loc[rebalDate, :] / prices.loc[yearAgo, :]) - 1 mom_1M = (prices.loc[rebalDate, :] / prices.loc[monthAgo, :]) - 1 momData = (mom_12M - mom_1M).dropna() return momData
def get_portfolio(factor, factorStyle = 'ratio'): rebalData_long = [] rebalData_short = [] for i in range(len(rebal_sche)): rebalDate_ = util.get_recentBday(rebal_sche[i], dateFormat = 'datetime') #print(rebalDate_) univ_ = getUniverse(marketInfo, mktcap, risk_1, risk_2, rebalDate_) print(len(univ_)) if factorStyle == 'ratio': factor = factor.loc[:,univ_] factor_ = getFactorData(factor, rebalDate_) mktcap_ = util.get_mktcap(factor_.index.values, rebalDate_, rebalDate_) ratio_ = get_priceRatio(mktcap_, factor_) long, short = get_longshort(ratio_, num_group = 10) longFinal = to_backtestFormat(long, rebalDate_) shortFinal = to_backtestFormat(short, rebalDate_) rebalData_long.append(longFinal) rebalData_short.append(shortFinal) elif factorStyle == 'Momentum': factor_mom = get_priceMom(univ_, rebalDate_) long, short = get_longshort(factor_mom, num_group = 10, asc = False) longFinal = to_backtestFormat(long, rebalDate_) shortFinal = to_backtestFormat(short, rebalDate_) rebalData_long.append(longFinal) rebalData_short.append(shortFinal) rebalData_long = pd.concat(rebalData_long).reset_index()[['date','code','weight']] rebalData_short = pd.concat(rebalData_short).reset_index()[['date','code','weight']] return rebalData_long, rebalData_short
def get_backtest_history(dollar_inv, rebalData, roundup=False, tradeCost=0.01): dollar_ongoing = dollar_inv basket_history = {} rebal_date = list(set(rebalData.date)) rebal_date.sort() tradeCost_history = {} turnover_history = {} weight_history = {} inv_money_list = [dollar_inv] inv_money_date = [rebal_date[0]] for i in tqdm(range(len(rebal_date))): if i < len(rebal_date) - 1: rebalDate = rebal_date[i] # 리밸런싱 시점 stock_list_i = rebalData[rebalData.date == rebal_date[i]].code # 기간별 종목 리스트 w_ = rebalData[rebalData.date == rebal_date[i]].weight weightData = pd.concat([stock_list_i, w_], axis=1).set_index('code') if i == 0: weightData['money'] = weightData[ 'weight'] * dollar_inv # 1기인 경우 초기 투자금으로 시작 else: weightData['money'] = weightData[ 'weight'] * dollar_ongoing # 1기 이후는 투자금의 매 기간별 마지막 시점에서의 금액 재투자 stock_price_ = util.get_stock_price( stock_list_i, util.get_recentBday(rebalDate), util.get_recentBday( rebalDate)).transpose() # 해당 일자의 바스켓의 주가 추출 weightData = pd.merge( weightData, stock_price_, how='inner', left_on=weightData.index, right_on=stock_price_.index).set_index('key_0') weightData.columns = ['weight', 'money', 'price'] weightData['n_stocks'] = weightData['money'] / weightData['price'] if roundup == True: # 초기 투입자금으로 투자가능한 종목별 주식수 (정수로 내림) weightData.n_stocks = np.floor(weightData.n_stocks) else: weightData.n_stocks = weightData.n_stocks basket_price = util.get_basket_history( weightData.index.values, weightData.n_stocks.values, util.get_recentBday(rebal_date[i]), util.get_recentBday(rebal_date[i + 1])) dollar_ongoing = basket_price.iloc[-1, :].values[ 0] # 투자금의 매 기간별 마지막 시점에서의 포트의 가치(금액) # 투자기간 마지막 시점 (다음리밸) 에서의 가격 last_price = util.get_stock_price( weightData.index.values, util.get_recentBday(rebal_date[i + 1]), util.get_recentBday(rebal_date[i + 1])).transpose() weightData = pd.merge(weightData, last_price, how='inner', left_on=weightData.index, right_on=last_price.index).set_index('key_0') weightData.columns = [ 'weight', 'money', 'price', 'n_stocks', 'last_price' ] weightData['last_weight'] = ( weightData.last_price * weightData.n_stocks) / ( weightData.last_price * weightData.n_stocks).sum() # 투자기간의 마지막 시점에서의 비중 new_weight = rebalData[rebalData.date == rebal_date[ i + 1]].set_index('code')['weight'] # 새로운 비중 new_weight = pd.Series(new_weight, name='new_weight') weightData = pd.concat([weightData, new_weight], axis=1) weightData['new_weight'] = weightData['new_weight'].fillna(0) weightData['weight'] = weightData['weight'].fillna(0) tradingCost = np.abs(weightData.new_weight - weightData.last_weight ).sum() * tradeCost * dollar_ongoing dollar_ongoing -= tradingCost basket_history[rebalDate] = basket_price inv_money_list += list(basket_price.values.squeeze()[1:-1]) inv_money_list += [dollar_ongoing] inv_money_date += list(basket_price.index[1:]) tradeCost_history[''.join([ x for x in str(rebal_date[i + 1])[:10] if x != '-' ])] = tradingCost turnover_history[''.join([ x for x in str(rebal_date[i + 1])[:10] if x != '-' ])] = tradingCost / dollar_ongoing weight_history[''.join([ x for x in str(rebal_date[i + 1])[:10] if x != '-' ])] = weightData elif i == len(rebal_date) - 1: rebalDate = rebal_date[i] # 리밸런싱 시점 #print(rebalDate) stock_list_i = rebalData[rebalData.date == rebal_date[i]].code # 기간별 종목 리스트 lastDay = datetime.datetime.today() - datetime.timedelta(2) w_ = rebalData[rebalData.date == rebal_date[i]].weight weightData = pd.concat([stock_list_i, w_], axis=1).set_index('code') if i == 0: weightData['money'] = weightData[ 'weight'] * dollar_inv # 1기인 경우 초기 투자금으로 시작 else: weightData['money'] = weightData[ 'weight'] * dollar_ongoing # 1기 이후는 투자금의 매 기간별 마지막 시점에서의 금액 재투자 stock_price_ = util.get_stock_price( stock_list_i, util.get_recentBday(rebalDate), util.get_recentBday( rebalDate)).transpose() # 해당 일자의 바스켓의 주가 추출 weightData = pd.merge( weightData, stock_price_, how='inner', left_on=weightData.index, right_on=stock_price_.index).set_index('key_0') weightData.columns = ['weight', 'money', 'price'] weightData['n_stocks'] = weightData['money'] / weightData['price'] if roundup == True: # 초기 투입자금으로 투자가능한 종목별 주식수 (정수로 내림) weightData.n_stocks = np.floor(weightData.n_stocks) else: weightData.n_stocks = weightData.n_stocks basket_price = util.get_basket_history( weightData.index.values, weightData.n_stocks.values, util.get_recentBday(rebal_date[i]), util.get_recentBday(lastDay)) dollar_ongoing = basket_price.iloc[-1, :].values[ 0] # 투자금의 매 기간별 마지막 시점에서의 포트의 가치(금액) #print(inv_money_list) # 투자기간 마지막 시점 (다음리밸) 에서의 가격 last_price = util.get_stock_price( weightData.index.values, util.get_recentBday(lastDay), util.get_recentBday(lastDay)).transpose() weightData = pd.merge(weightData, last_price, how='inner', left_on=weightData.index, right_on=last_price.index).set_index('key_0') weightData.columns = [ 'weight', 'money', 'price', 'n_stocks', 'last_price' ] weightData['last_weight'] = ( weightData.last_price * weightData.n_stocks) / ( weightData.last_price * weightData.n_stocks).sum() # 투자기간의 마지막 시점에서의 비중 weightData['new_weight'] = 0 tradingCost = 0 dollar_ongoing -= tradingCost basket_history[rebalDate] = basket_price inv_money_list += list(basket_price.values.squeeze()[1:-1]) inv_money_list += [dollar_ongoing] inv_money_date += list(basket_price.index[1:]) tradeCost_history[''.join( [x for x in str(lastDay)[:10] if x != '-'])] = tradingCost turnover_history[''.join([ x for x in str(lastDay)[:10] if x != '-' ])] = tradingCost / dollar_ongoing weight_history[''.join([x for x in str(lastDay)[:10] if x != '-'])] = weightData inv_money_history = pd.DataFrame(inv_money_list, index=inv_money_date) return inv_money_history, tradeCost_history, turnover_history, weight_history
df = pd.DataFrame(index=range(len(codes)), columns=['date', 'code', 'weight']) df['code'] = codes df['weight'] = np.ones(len(codes)) / len(codes) df['date'] = rebalDate return df rebalData_long = [] rebalData_short = [] num_group = 5 method = 'integrated' for i in tqdm(range(len(rebal_sche))): date_spot = util.get_recentBday(rebal_sche[i], dateFormat='datetime') univ_ = util.getUniverse(marketInfo, mktcap, risk_1, risk_2, date_spot) psr_spot = util.getFinancialData(factor_PSR, date_spot)[univ_] pbr_spot = util.getFinancialData(factor_PBR, date_spot)[univ_] # I-1. Integrated Method (Signal Blend, 개별 팩터 스코어를 모두 더해 한번에 주식을 뽑는 방법) if method == 'integrated': factorName = ['sales', 'book'] # factorName = ['book'] multifactor_df = pd.concat([psr_spot, pbr_spot], axis=1, sort=False) # multifactor_df = pd.concat([pbr_spot], axis = 1, sort = False) multifactor_df.columns = factorName mktcaps = util.get_mktcap(multifactor_df.index.values, date_spot, date_spot)