def compute_returns(): global stats_dict, units_save_dict stop_inv_dict = defaultdict(lambda: None) inv_dict = defaultdict(float) units_dict = defaultdict(float) cashflows_dict = defaultdict(list) default_inv = common.mnt_inv max_total_inv = default_inv * (num_rows - 14) for i,r in enumerate(nav_data): if i < 13 or i == (num_rows - 1): continue dt = datetime.strptime(r.split(',')[0], '%d-%m-%Y') nav_line = r.split(',')[1:] nav_dict = common.get_fund_nav_dict(fund_names, nav_line) wealth = get_fund_wealth(units_dict, nav_dict) index = i - 12 for fund in fund_names: nav = nav_dict[fund] fund_value = wealth[fund] fund_inv = inv_dict[fund] mnt_inv = max(default_inv, default_inv * index - fund_value) mnt_inv = min(mnt_inv, max_total_inv - fund_inv) inv_dict[fund] += mnt_inv units = mnt_inv / nav units_dict[fund] += units units_save_dict[fund].append(units) cf = (dt, -mnt_inv) cashflows_dict[fund].append(cf) if fund_inv + mnt_inv == max_total_inv and not stop_inv_dict[fund]: stop_inv_dict[fund] = index last_line = nav_data[num_rows - 1].split(',') curr_dt = datetime.strptime(last_line[0], '%d-%m-%Y') curr_nav_line = last_line[1:] curr_nav_dict = common.get_fund_nav_dict(fund_names, curr_nav_line) for fund in fund_names: investment = inv_dict[fund] stop_inv = stop_inv_dict[fund] wealth = units_dict[fund] * curr_nav_dict[fund] abs_return = (wealth / investment) - 1 cf = (curr_dt, wealth) cashflows_dict[fund].append(cf) ann_return = common.xirr(cashflows_dict[fund]) stats = [investment, wealth, abs_return, ann_return, stop_inv] stats_dict[fund].extend(stats)
def compute_returns(): global stats_dict, units_save_dict stop_inv_dict = defaultdict(lambda: None) inv_dict = defaultdict(float) units_dict = defaultdict(float) cashflows_dict = defaultdict(list) default_inv = common.mnt_inv max_total_inv = default_inv * (num_rows - 14) for i, r in enumerate(nav_data): if i < 13 or i == (num_rows - 1): continue dt = datetime.strptime(r.split(',')[0], '%d-%m-%Y') nav_line = r.split(',')[1:] nav_dict = common.get_fund_nav_dict(fund_names, nav_line) wealth = get_fund_wealth(units_dict, nav_dict) index = i - 12 for fund in fund_names: nav = nav_dict[fund] fund_value = wealth[fund] fund_inv = inv_dict[fund] mnt_inv = max(default_inv, default_inv * index - fund_value) mnt_inv = min(mnt_inv, max_total_inv - fund_inv) inv_dict[fund] += mnt_inv units = mnt_inv / nav units_dict[fund] += units units_save_dict[fund].append(units) cf = (dt, -mnt_inv) cashflows_dict[fund].append(cf) if fund_inv + mnt_inv == max_total_inv and not stop_inv_dict[fund]: stop_inv_dict[fund] = index last_line = nav_data[num_rows - 1].split(',') curr_dt = datetime.strptime(last_line[0], '%d-%m-%Y') curr_nav_line = last_line[1:] curr_nav_dict = common.get_fund_nav_dict(fund_names, curr_nav_line) for fund in fund_names: investment = inv_dict[fund] stop_inv = stop_inv_dict[fund] wealth = units_dict[fund] * curr_nav_dict[fund] abs_return = (wealth / investment) - 1 cf = (curr_dt, wealth) cashflows_dict[fund].append(cf) ann_return = common.xirr(cashflows_dict[fund]) stats = [investment, wealth, abs_return, ann_return, stop_inv] stats_dict[fund].extend(stats)
def compute_returns(): global perf_data total_inv = 0 cashflows = [] units_dict = defaultdict(float) max_total_inv = common.mnt_inv * (num_rows - 14) prev_inv = common.mnt_inv for i,r in enumerate(nav_data): if i < 13 or i == (num_rows - 1): continue dt = datetime.strptime(r.split(',')[0], '%d-%m-%Y') nav_line = r.split(',')[1:] nav_dict = common.get_fund_nav_dict(fund_names, nav_line) index = i - 13 j = i - 12 fund = sharpe_rank_data[j].split(',')[1] nav = nav_dict[fund] ma = ma_dict[fund][i - 13] allowed_inv = max_total_inv - total_inv mnt_inv = get_mnt_inv(index, nav, ma, prev_inv) mnt_inv = min(mnt_inv, allowed_inv) cf = (dt, -mnt_inv) cashflows.append(cf) units = mnt_inv / nav units_dict[fund] += units total_inv += mnt_inv prev_inv = mnt_inv save_inv_data(units_dict) last_line = nav_data[num_rows - 1].split(',') curr_dt = datetime.strptime(last_line[0], '%d-%m-%Y') curr_nav_line = last_line[1:] curr_nav_dict = common.get_fund_nav_dict(fund_names, curr_nav_line) wealth = 0 for fund in units_dict: wealth += units_dict[fund] * curr_nav_dict[fund] cf = (curr_dt, wealth) cashflows.append(cf) abs_return = (wealth / total_inv) - 1 ann_return = common.xirr(cashflows) perf_data = (total_inv, wealth, abs_return, ann_return)
def compute_returns(): global stats_data cashflows = [] units_dict = defaultdict(float) num_funds = len(fund_names) default_inv = common.mnt_inv mnt_inv = (default_inv * 1.0) / num_funds print 'monthly investment - %f' % mnt_inv total_inv = 0 for i, r in enumerate(nav_data): if i < 13 or i == (num_rows - 1): continue dt = datetime.strptime(r.split(',')[0], '%d-%m-%Y') nav_line = r.split(',')[1:] nav_dict = common.get_fund_nav_dict(fund_names, nav_line) cf = (dt, -default_inv) cashflows.append(cf) for fund in fund_names: nav = nav_dict[fund] units = mnt_inv / nav units_dict[fund] += units total_inv += mnt_inv last_line = nav_data[num_rows - 1].split(',') curr_dt = datetime.strptime(last_line[0], '%d-%m-%Y') curr_nav_line = last_line[1:] curr_nav_dict = common.get_fund_nav_dict(fund_names, curr_nav_line) wealth = 0 for fund in fund_names: wealth += units_dict[fund] * curr_nav_dict[fund] cf = (curr_dt, wealth) cashflows.append(cf) abs_return = (wealth / total_inv) - 1 ann_return = common.xirr(cashflows) stat = [total_inv, wealth, abs_return, ann_return] stats_data.extend(stat)
def compute_returns(): global perf_data total_inv = 0 cashflows = [] units_dict = defaultdict(float) for i,r in enumerate(nav_data): if i < 13 or i == (num_rows - 1): continue dt = datetime.strptime(r.split(',')[0], '%d-%m-%Y') nav_line = r.split(',')[1:] nav_dict = common.get_fund_nav_dict(fund_names, nav_line) total_inv += mnt_inv cf = (dt, -mnt_inv) cashflows.append(cf) j = i - 12 fund = sharpe_rank_data[j].split(',')[1] nav = nav_dict[fund] units = mnt_inv / nav units_dict[fund] += units save_inv_data(units_dict) last_line = nav_data[num_rows - 1].split(',') curr_dt = datetime.strptime(last_line[0], '%d-%m-%Y') curr_nav_line = last_line[1:] curr_nav_dict = common.get_fund_nav_dict(fund_names, curr_nav_line) wealth = 0 for fund in units_dict: wealth += units_dict[fund] * curr_nav_dict[fund] cf = (curr_dt, wealth) cashflows.append(cf) abs_return = (wealth / total_inv) - 1 ann_return = common.xirr(cashflows) perf_data = (total_inv, wealth, abs_return, ann_return)
def compute_returns(): global perf_data total_inv = 0 cashflows = [] units_dict = defaultdict(float) for i, r in enumerate(nav_data): if i < 13 or i == (num_rows - 1): continue dt = datetime.strptime(r.split(',')[0], '%d-%m-%Y') nav_line = r.split(',')[1:] nav_dict = common.get_fund_nav_dict(fund_names, nav_line) total_inv += mnt_inv cf = (dt, -mnt_inv) cashflows.append(cf) j = i - 12 fund = sharpe_rank_data[j].split(',')[1] nav = nav_dict[fund] units = mnt_inv / nav units_dict[fund] += units save_inv_data(units_dict) last_line = nav_data[num_rows - 1].split(',') curr_dt = datetime.strptime(last_line[0], '%d-%m-%Y') curr_nav_line = last_line[1:] curr_nav_dict = common.get_fund_nav_dict(fund_names, curr_nav_line) wealth = 0 for fund in units_dict: wealth += units_dict[fund] * curr_nav_dict[fund] cf = (curr_dt, wealth) cashflows.append(cf) abs_return = (wealth / total_inv) - 1 ann_return = common.xirr(cashflows) perf_data = (total_inv, wealth, abs_return, ann_return)
def compute_returns(): inv_dict = defaultdict(float) units_dict = defaultdict(float) cashflows_dict = defaultdict(list) for i,r in enumerate(nav_data): if i < 13 or i == (num_rows - 1): continue dt = datetime.strptime(r.split(',')[0], '%d-%m-%Y') nav_line = r.split(',')[1:] nav_dict = common.get_fund_nav_dict(fund_names, nav_line) cf = (dt, -mnt_inv) for fund in fund_names: nav = nav_dict[fund] units = mnt_inv / nav inv_dict[fund] += mnt_inv units_dict[fund] += units cashflows_dict[fund].append(cf) last_line = nav_data[num_rows - 1].split(',') curr_dt = datetime.strptime(last_line[0], '%d-%m-%Y') curr_nav_line = last_line[1:] curr_nav_dict = {} for fund, nav in zip(fund_names, curr_nav_line): curr_nav_dict[fund] = float(nav) for fund in fund_names: investment = inv_dict[fund] wealth = units_dict[fund] * curr_nav_dict[fund] cf = (curr_dt, wealth) cashflows_dict[fund].append(cf) abs_return = (wealth / investment) - 1 ann_return = common.xirr(cashflows_dict[fund]) perf_dict[fund] = (investment, wealth, abs_return, ann_return)
def run(nav_file): # create data directory common.create_dir(data_dir) # read nav data nav_data = common.read_from_file(nav_file) # remove first 12 entries in nav_data # to compare results with benchmark del nav_data[1:13] # retrieve fund names # the first column (date) is skipped fund_names = nav_data[0].split(',')[1:] # initialize cashflows = [] returns_halfyr = common.init_array_dict(fund_names) returns_annual = common.init_array_dict(fund_names) units_dict_halfyr = common.init_dict(fund_names) units_dict_annual = common.init_dict(fund_names) units_dict_overall = common.init_dict(fund_names) # remove header line del nav_data[0] # compute cashflows and returns cnt = len(nav_data) for i in range(0, cnt): row_data = nav_data[i].split(',') dt = datetime.strptime(row_data[0], '%d-%m-%Y') fund_nav = row_data[1:] fund_nav_dict = common.get_fund_nav_dict(fund_names, fund_nav) # half-yearly returns for each fund if i % 6 == 0 and i > 0: wealth = common.get_fund_wealth(fund_nav_dict, units_dict_halfyr) for fund in fund_names: cashflows_halfyr = cashflows[i-6:i] # slice last 6 months cashflows cf = (dt, wealth[fund]) cashflows_halfyr.append(cf) ret = common.xirr(cashflows_halfyr) returns_halfyr[fund].append(ret) # clean up for next pass units_dict_halfyr = common.init_dict(fund_names) # annual returns for each fund if i % 12 == 0 and i > 0: wealth = common.get_fund_wealth(fund_nav_dict, units_dict_annual) for fund in fund_names: cashflows_annual = cashflows[i-12:i] # slice last 12 months cashflows cf = (dt, wealth[fund]) cashflows_annual.append(cf) ret = common.xirr(cashflows_annual) returns_annual[fund].append(ret) # clean up for next pass units_dict_annual = common.init_dict(fund_names) # no investment on the last date if i == cnt - 1: break # invested units for fund in fund_names: nav = fund_nav_dict[fund] units = mnt_inv / nav units_dict_halfyr[fund] += units units_dict_annual[fund] += units units_dict_overall[fund] += units # cash outflow cf = (dt, -mnt_inv) cashflows.append(cf) file_data = [] header_line = \ 'Fund,Investment,Wealth,Absolute Return,Annualized Return,' + \ 'Half-Yr Return Mean,Half-Yr Return Std Dev,Half-Yr Sharpe,' + \ 'Annual Return Mean,Annual Return Std Dev,Annual Sharpe' file_data.append(header_line) # total investment num_inv = len(cashflows) total_inv = num_inv * mnt_inv # final wealth nav_line = nav_data[cnt - 1].split(',')[1:] fund_nav_dict = common.get_fund_nav_dict(fund_names, nav_line) wealth = common.get_fund_wealth(fund_nav_dict, units_dict_overall) # performance stats for each fund last_date = nav_data[cnt - 1].split(',')[0] dt = datetime.strptime(last_date, '%d-%m-%Y') for fund in sorted(fund_names): fund_cashflows = cashflows[:] cf = (dt, wealth[fund]) fund_cashflows.append(cf) abs_return = ((wealth[fund] / total_inv) - 1) ann_return = common.xirr(fund_cashflows) hfr = returns_halfyr[fund] halfyr_rf_rate = common.get_rf_rate('half-yearly') halfyr_return_mean = numpy.mean(hfr) halfyr_return_std = numpy.std(hfr) halfyr_sharpe = common.get_sharpe_ratio(hfr, halfyr_rf_rate) afr = returns_annual[fund] annual_rf_rate = common.get_rf_rate('annual') annual_return_mean = numpy.mean(afr) annual_return_std = numpy.std(afr) annual_sharpe = common.get_sharpe_ratio(afr, annual_rf_rate) line_data = \ fund + ',' + str(total_inv) + ',' + str(wealth[fund]) + ',' + \ str(abs_return) + ',' + str(ann_return) + ',' + \ str(halfyr_return_mean) + ',' + str(halfyr_return_std) + ',' + \ str(halfyr_sharpe) + ',' + str(annual_return_mean) + ',' + \ str(annual_return_std) + ',' + str(annual_sharpe) file_data.append(line_data) regular_sip_file = os.path.join(data_dir, regular_sip_file_name) common.write_to_file(regular_sip_file, file_data)
def run(nav_file, rank_file): """ Generates return statistics based on sharpe ratio ranking data. """ # create data directory common.create_dir(data_dir) # read data files nav_data = common.read_from_file(nav_file) rank_data = common.read_from_file(rank_file) # remove redundant entries in nav_data target_date = rank_data[1].split(',')[0] common.trim_data(nav_data, target_date) assert len(nav_data) == len(rank_data) # retrieve fund names # the first column (date) is skipped fund_names = nav_data[0].split(',')[1:] # initialize cashflows_halfyr = [] cashflows_annual = [] cashflows_overall = [] returns_halfyr = [] returns_annual = [] units_dict_halfyr = common.init_dict(fund_names) units_dict_annual = common.init_dict(fund_names) units_dict_overall = common.init_dict(fund_names) # remove header line del nav_data[0] del rank_data[0] # compute cashflows and returns cnt = len(nav_data) for i in range(0, cnt): (date, fund, nav) = rank_data[i].split(',') dt = datetime.strptime(date, '%d-%m-%Y') # half-yearly returns if i % 6 == 0 and i > 0: nav_line = nav_data[i].split(',')[1:] fund_nav_dict = common.get_fund_nav_dict(fund_names, nav_line) wealth = get_wealth(fund_nav_dict, units_dict_halfyr) cf = (dt, wealth) cashflows_halfyr.append(cf) ret = common.xirr(cashflows_halfyr) returns_halfyr.append(ret) # clean up for next pass del cashflows_halfyr[:] units_dict_halfyr[f] = common.init_dict(fund_names) # annual returns if i % 12 == 0 and i > 0: nav_line = nav_data[i].split(',')[1:] nav_dict = common.get_fund_nav_dict(fund_names, nav_line) wealth = get_wealth(nav_dict, units_dict_annual) cf = (dt, wealth) cashflows_annual.append(cf) ret = common.xirr(cashflows_annual) returns_annual.append(ret) # clean up for next pass del cashflows_annual[:] units_dict_annual[f] = common.init_dict(fund_names) # no investment on the last date if i == cnt - 1: break # units invested units = mnt_inv / float(nav) units_dict_halfyr[fund] += units units_dict_annual[fund] += units units_dict_overall[fund] += units # cash outflow cf = (dt, -mnt_inv) cashflows_halfyr.append(cf) cashflows_annual.append(cf) cashflows_overall.append(cf) file_data = [] # investment details file_data.append('Investment Details') file_data.append('Fund,Units') for f in units_dict_overall: if units_dict_overall[f] > 0: line_data = f + ',' + str(units_dict_overall[f]) file_data.append(line_data) file_data.append('\n') # total investment num_inv = len(cashflows_overall) total_inv = num_inv * mnt_inv file_data.append('Investment,' + str(total_inv)) # final wealth nav_line = nav_data[cnt - 1].split(',')[1:] fund_nav_dict = common.get_fund_nav_dict(fund_names, nav_line) wealth = get_wealth(fund_nav_dict, units_dict_overall) file_data.append('Wealth,' + str(wealth)) # absolute return abs_return = ((wealth / total_inv) - 1) file_data.append('Absolute Return,' + str(abs_return)) # annualized return last_date = nav_data[cnt - 1].split(',')[0] dt = datetime.strptime(last_date, '%d-%m-%Y') cf = (dt, wealth) cashflows_overall.append(cf) annual_return = common.xirr(cashflows_overall) file_data.append('Annualized Return,' + str(annual_return)) file_data.append('\n') file_data.append('Stats,Mean,Std Deviation, Sharpe Ratio') # half-yearly return stats halfyr_rf_rate = common.get_rf_rate('half-yearly') halfyr_mean = numpy.mean(returns_halfyr) halfyr_stdev = numpy.std(returns_halfyr) halfyr_sharpe = common.get_sharpe_ratio(returns_halfyr, halfyr_rf_rate) file_data.append('Half-Yearly,' + str(halfyr_mean) + ',' + str(halfyr_stdev) + ',' + str(halfyr_sharpe)) # annual return stats annual_rf_rate = common.get_rf_rate('annual') annual_mean = numpy.mean(returns_annual) annual_stdev = numpy.std(returns_annual) annual_sharpe = common.get_sharpe_ratio(returns_annual, annual_rf_rate) file_data.append('Annual,' + str(annual_mean) + ',' + str(annual_stdev) + ',' + str(annual_sharpe)) # save stats to file benchmark_file = os.path.join(data_dir, benchmark_file_name) common.write_to_file(benchmark_file, file_data)
def run(nav_file, ma_type): nav_data = common.read_from_file(nav_file) fund_names = nav_data[0].split(',')[1:] del nav_data[1:7] ma_data = get_ma_data(nav_data) del nav_data[0:7] cashflows = common.init_array_dict(fund_names) fund_inv_dict = common.init_dict(fund_names) fund_corpus_dict = common.init_dict(fund_names) fund_corpus_index_dict = common.init_array_dict(fund_names) last_inv_dict = common.init_dict(fund_names, default_inv) returns_halfyr = common.init_array_dict(fund_names) returns_annual = common.init_array_dict(fund_names) units_dict_halfyr = common.init_dict(fund_names) units_dict_annual = common.init_dict(fund_names) units_dict_overall = common.init_dict(fund_names) cnt = len(nav_data) max_total_inv = default_inv * (cnt - 1) for i in xrange(0, cnt): row_data = nav_data[i].split(',') dt = datetime.strptime(row_data[0], '%d-%m-%Y') fund_nav = row_data[1:] fund_nav_dict = common.get_fund_nav_dict(fund_names, fund_nav) # half-yearly returns for each fund if i % 6 == 0 and i > 0: wealth = common.get_fund_wealth(fund_nav_dict, units_dict_halfyr) for fund in fund_names: start_corpus = fund_corpus_index_dict[fund][i-7] end_corpus = fund_corpus_index_dict[fund][i-1] corpus_wealth = end_corpus - start_corpus total_wealth = wealth[fund] + corpus_wealth cashflows_halfyr = cashflows[fund][i-6:i] # slice last 6 months cashflows if is_cashflow_missing(cashflows_halfyr): continue cf = (dt, total_wealth) cashflows_halfyr.append(cf) ret = common.xirr(cashflows_halfyr) returns_halfyr[fund].append(ret) # clean up units_dict_halfyr = common.init_dict(fund_names) # annual returns for each fund if i % 12 == 0 and i > 0: wealth = common.get_fund_wealth(fund_nav_dict, units_dict_annual) for fund in fund_names: start_corpus = fund_corpus_index_dict[fund][i-13] end_corpus = fund_corpus_index_dict[fund][i-1] corpus_wealth = end_corpus - start_corpus total_wealth = wealth[fund] + corpus_wealth cashflows_annual = cashflows[fund][i-12:i] # slice last 12 months cashflows if is_cashflow_missing(cashflows_annual): continue cf = (dt, wealth[fund] + fund_corpus_dict[fund]) cashflows_annual.append(cf) ret = common.xirr(cashflows_annual) returns_annual[fund].append(ret) # clean up units_dict_annual = common.init_dict(fund_names) # no investment on the last date if i == cnt - 1: break for f in fund_names: # cap total investment allowed_inv = max_total_inv - fund_inv_dict[f] prev_inv = last_inv_dict[f] nav = fund_nav_dict[f] ma = ma_data[f][i] # equity investment mnt_inv = get_mnt_inv(ma_type, prev_inv, nav, ma) mnt_inv = min(mnt_inv, allowed_inv) last_inv_dict[f] = mnt_inv allowed_inv -= mnt_inv # debt investment corpus = fund_corpus_dict[f] debt_inv = default_inv - mnt_inv if debt_inv < 0: debt_inv = -min(mnt_inv - default_inv, corpus) else: debt_inv = min(debt_inv, allowed_inv) # corpus investment + interest corpus += debt_inv interest = corpus * int_rate corpus += interest fund_corpus_dict[f] = corpus fund_corpus_index_dict[f].append(corpus) # total investment total_inv = mnt_inv + debt_inv fund_inv_dict[f] += total_inv # invested units units = mnt_inv / nav units_dict_overall[f] += units units_dict_halfyr[f] += units units_dict_annual[f] += units # cashflows cf = (dt, -total_inv) cashflows[f].append(cf) # debugging # if f == 'Birla_Advantage_Fund': # print '%d\t%d\t%d\t%.2f\t%d\t%d' % (mnt_inv, debt_inv, round(fund_inv_dict[f]), units, -total_inv, round(corpus)) file_data = [] header_line = \ 'Fund,Investment,Wealth,Absolute Return,Annualized Return,' + \ 'Half-Yr Return Mean,Half-Yr Return Std Dev,Half-Yr Sharpe,' + \ 'Annual Return Mean,Annual Return Std Dev,Annual Sharpe' file_data.append(header_line) # final wealth nav_line = nav_data[cnt - 1].split(',')[1:] fund_nav_dict = common.get_fund_nav_dict(fund_names, nav_line) wealth = common.get_fund_wealth(fund_nav_dict, units_dict_overall) # performance stats for each fund last_date = nav_data[cnt - 1].split(',')[0] dt = datetime.strptime(last_date, '%d-%m-%Y') for fund in sorted(fund_names): total_wealth = wealth[fund] + fund_corpus_dict[fund] fund_cashflows = cashflows[fund][:] cf = (dt, total_wealth) fund_cashflows.append(cf) fund_inv = fund_inv_dict[fund] abs_return = ((total_wealth / fund_inv) - 1) ann_return = common.xirr(fund_cashflows) hfr = returns_halfyr[fund] halfyr_rf_rate = common.get_rf_rate('half-yearly') halfyr_return_mean = numpy.mean(hfr) halfyr_return_std = numpy.std(hfr) halfyr_sharpe = common.get_sharpe_ratio(hfr, halfyr_rf_rate) afr = returns_annual[fund] annual_rf_rate = common.get_rf_rate('annual') annual_return_mean = numpy.mean(afr) annual_return_std = numpy.std(afr) annual_sharpe = common.get_sharpe_ratio(afr, annual_rf_rate) line_data = \ fund + ',' + str(fund_inv) + ',' + str(total_wealth) + ',' + \ str(abs_return) + ',' + str(ann_return) + ',' + \ str(halfyr_return_mean) + ',' + str(halfyr_return_std) + ',' + \ str(halfyr_sharpe) + ',' + str(annual_return_mean) + ',' + \ str(annual_return_std) + ',' + str(annual_sharpe) file_data.append(line_data) ma_file_name = 'ma_with_debt_' + ma_type + '.csv' ma_file = os.path.join(data_dir, ma_file_name) common.write_to_file(ma_file, file_data)
def run(nav_file, ma_type): nav_data = common.read_from_file(nav_file) fund_names = nav_data[0].split(',')[1:] del nav_data[1:7] ma_data = get_ma_data(nav_data) del nav_data[0:7] cashflows = common.init_array_dict(fund_names) fund_inv_dict = common.init_dict(fund_names) fund_corpus_dict = common.init_dict(fund_names) fund_corpus_index_dict = common.init_array_dict(fund_names) last_inv_dict = common.init_dict(fund_names, default_inv) returns_halfyr = common.init_array_dict(fund_names) returns_annual = common.init_array_dict(fund_names) units_dict_halfyr = common.init_dict(fund_names) units_dict_annual = common.init_dict(fund_names) units_dict_overall = common.init_dict(fund_names) cnt = len(nav_data) max_total_inv = default_inv * (cnt - 1) for i in xrange(0, cnt): row_data = nav_data[i].split(',') dt = datetime.strptime(row_data[0], '%d-%m-%Y') fund_nav = row_data[1:] fund_nav_dict = common.get_fund_nav_dict(fund_names, fund_nav) # half-yearly returns for each fund if i % 6 == 0 and i > 0: wealth = common.get_fund_wealth(fund_nav_dict, units_dict_halfyr) for fund in fund_names: start_corpus = fund_corpus_index_dict[fund][i - 7] end_corpus = fund_corpus_index_dict[fund][i - 1] corpus_wealth = end_corpus - start_corpus total_wealth = wealth[fund] + corpus_wealth cashflows_halfyr = cashflows[fund][ i - 6:i] # slice last 6 months cashflows if is_cashflow_missing(cashflows_halfyr): continue cf = (dt, total_wealth) cashflows_halfyr.append(cf) ret = common.xirr(cashflows_halfyr) returns_halfyr[fund].append(ret) # clean up units_dict_halfyr = common.init_dict(fund_names) # annual returns for each fund if i % 12 == 0 and i > 0: wealth = common.get_fund_wealth(fund_nav_dict, units_dict_annual) for fund in fund_names: start_corpus = fund_corpus_index_dict[fund][i - 13] end_corpus = fund_corpus_index_dict[fund][i - 1] corpus_wealth = end_corpus - start_corpus total_wealth = wealth[fund] + corpus_wealth cashflows_annual = cashflows[fund][ i - 12:i] # slice last 12 months cashflows if is_cashflow_missing(cashflows_annual): continue cf = (dt, wealth[fund] + fund_corpus_dict[fund]) cashflows_annual.append(cf) ret = common.xirr(cashflows_annual) returns_annual[fund].append(ret) # clean up units_dict_annual = common.init_dict(fund_names) # no investment on the last date if i == cnt - 1: break for f in fund_names: # cap total investment allowed_inv = max_total_inv - fund_inv_dict[f] prev_inv = last_inv_dict[f] nav = fund_nav_dict[f] ma = ma_data[f][i] # equity investment mnt_inv = get_mnt_inv(ma_type, prev_inv, nav, ma) mnt_inv = min(mnt_inv, allowed_inv) last_inv_dict[f] = mnt_inv allowed_inv -= mnt_inv # debt investment corpus = fund_corpus_dict[f] debt_inv = default_inv - mnt_inv if debt_inv < 0: debt_inv = -min(mnt_inv - default_inv, corpus) else: debt_inv = min(debt_inv, allowed_inv) # corpus investment + interest corpus += debt_inv interest = corpus * int_rate corpus += interest fund_corpus_dict[f] = corpus fund_corpus_index_dict[f].append(corpus) # total investment total_inv = mnt_inv + debt_inv fund_inv_dict[f] += total_inv # invested units units = mnt_inv / nav units_dict_overall[f] += units units_dict_halfyr[f] += units units_dict_annual[f] += units # cashflows cf = (dt, -total_inv) cashflows[f].append(cf) # debugging # if f == 'Birla_Advantage_Fund': # print '%d\t%d\t%d\t%.2f\t%d\t%d' % (mnt_inv, debt_inv, round(fund_inv_dict[f]), units, -total_inv, round(corpus)) file_data = [] header_line = \ 'Fund,Investment,Wealth,Absolute Return,Annualized Return,' + \ 'Half-Yr Return Mean,Half-Yr Return Std Dev,Half-Yr Sharpe,' + \ 'Annual Return Mean,Annual Return Std Dev,Annual Sharpe' file_data.append(header_line) # final wealth nav_line = nav_data[cnt - 1].split(',')[1:] fund_nav_dict = common.get_fund_nav_dict(fund_names, nav_line) wealth = common.get_fund_wealth(fund_nav_dict, units_dict_overall) # performance stats for each fund last_date = nav_data[cnt - 1].split(',')[0] dt = datetime.strptime(last_date, '%d-%m-%Y') for fund in sorted(fund_names): total_wealth = wealth[fund] + fund_corpus_dict[fund] fund_cashflows = cashflows[fund][:] cf = (dt, total_wealth) fund_cashflows.append(cf) fund_inv = fund_inv_dict[fund] abs_return = ((total_wealth / fund_inv) - 1) ann_return = common.xirr(fund_cashflows) hfr = returns_halfyr[fund] halfyr_rf_rate = common.get_rf_rate('half-yearly') halfyr_return_mean = numpy.mean(hfr) halfyr_return_std = numpy.std(hfr) halfyr_sharpe = common.get_sharpe_ratio(hfr, halfyr_rf_rate) afr = returns_annual[fund] annual_rf_rate = common.get_rf_rate('annual') annual_return_mean = numpy.mean(afr) annual_return_std = numpy.std(afr) annual_sharpe = common.get_sharpe_ratio(afr, annual_rf_rate) line_data = \ fund + ',' + str(fund_inv) + ',' + str(total_wealth) + ',' + \ str(abs_return) + ',' + str(ann_return) + ',' + \ str(halfyr_return_mean) + ',' + str(halfyr_return_std) + ',' + \ str(halfyr_sharpe) + ',' + str(annual_return_mean) + ',' + \ str(annual_return_std) + ',' + str(annual_sharpe) file_data.append(line_data) ma_file_name = 'ma_with_debt_' + ma_type + '.csv' ma_file = os.path.join(data_dir, ma_file_name) common.write_to_file(ma_file, file_data)
def run(nav_file): # create data directory common.create_dir(data_dir) # read nav data nav_data = common.read_from_file(nav_file) # remove first 12 entries in nav_data # to compare results with benchmark del nav_data[1:13] # retrieve fund names # the first column (date) is skipped fund_names = nav_data[0].split(',')[1:] # initialize cashflows = [] returns_halfyr = common.init_array_dict(fund_names) returns_annual = common.init_array_dict(fund_names) units_dict_halfyr = common.init_dict(fund_names) units_dict_annual = common.init_dict(fund_names) units_dict_overall = common.init_dict(fund_names) # remove header line del nav_data[0] # compute cashflows and returns cnt = len(nav_data) for i in range(0, cnt): row_data = nav_data[i].split(',') dt = datetime.strptime(row_data[0], '%d-%m-%Y') fund_nav = row_data[1:] fund_nav_dict = common.get_fund_nav_dict(fund_names, fund_nav) # half-yearly returns for each fund if i % 6 == 0 and i > 0: wealth = common.get_fund_wealth(fund_nav_dict, units_dict_halfyr) for fund in fund_names: cashflows_halfyr = cashflows[ i - 6:i] # slice last 6 months cashflows cf = (dt, wealth[fund]) cashflows_halfyr.append(cf) ret = common.xirr(cashflows_halfyr) returns_halfyr[fund].append(ret) # clean up for next pass units_dict_halfyr = common.init_dict(fund_names) # annual returns for each fund if i % 12 == 0 and i > 0: wealth = common.get_fund_wealth(fund_nav_dict, units_dict_annual) for fund in fund_names: cashflows_annual = cashflows[ i - 12:i] # slice last 12 months cashflows cf = (dt, wealth[fund]) cashflows_annual.append(cf) ret = common.xirr(cashflows_annual) returns_annual[fund].append(ret) # clean up for next pass units_dict_annual = common.init_dict(fund_names) # no investment on the last date if i == cnt - 1: break # invested units for fund in fund_names: nav = fund_nav_dict[fund] units = mnt_inv / nav units_dict_halfyr[fund] += units units_dict_annual[fund] += units units_dict_overall[fund] += units # cash outflow cf = (dt, -mnt_inv) cashflows.append(cf) file_data = [] header_line = \ 'Fund,Investment,Wealth,Absolute Return,Annualized Return,' + \ 'Half-Yr Return Mean,Half-Yr Return Std Dev,Half-Yr Sharpe,' + \ 'Annual Return Mean,Annual Return Std Dev,Annual Sharpe' file_data.append(header_line) # total investment num_inv = len(cashflows) total_inv = num_inv * mnt_inv # final wealth nav_line = nav_data[cnt - 1].split(',')[1:] fund_nav_dict = common.get_fund_nav_dict(fund_names, nav_line) wealth = common.get_fund_wealth(fund_nav_dict, units_dict_overall) # performance stats for each fund last_date = nav_data[cnt - 1].split(',')[0] dt = datetime.strptime(last_date, '%d-%m-%Y') for fund in sorted(fund_names): fund_cashflows = cashflows[:] cf = (dt, wealth[fund]) fund_cashflows.append(cf) abs_return = ((wealth[fund] / total_inv) - 1) ann_return = common.xirr(fund_cashflows) hfr = returns_halfyr[fund] halfyr_rf_rate = common.get_rf_rate('half-yearly') halfyr_return_mean = numpy.mean(hfr) halfyr_return_std = numpy.std(hfr) halfyr_sharpe = common.get_sharpe_ratio(hfr, halfyr_rf_rate) afr = returns_annual[fund] annual_rf_rate = common.get_rf_rate('annual') annual_return_mean = numpy.mean(afr) annual_return_std = numpy.std(afr) annual_sharpe = common.get_sharpe_ratio(afr, annual_rf_rate) line_data = \ fund + ',' + str(total_inv) + ',' + str(wealth[fund]) + ',' + \ str(abs_return) + ',' + str(ann_return) + ',' + \ str(halfyr_return_mean) + ',' + str(halfyr_return_std) + ',' + \ str(halfyr_sharpe) + ',' + str(annual_return_mean) + ',' + \ str(annual_return_std) + ',' + str(annual_sharpe) file_data.append(line_data) regular_sip_file = os.path.join(data_dir, regular_sip_file_name) common.write_to_file(regular_sip_file, file_data)
def compute_returns(): global stats_dict, units_save_dict stop_inv_dict = defaultdict(lambda: None) inv_dict = defaultdict(float) last_inv_dict = defaultdict(lambda: common.mnt_inv) units_dict = defaultdict(float) cashflows_dict = defaultdict(list) # why (num_rows - 14) # ignore header, first 12 rows and last row max_total_inv = common.mnt_inv * (num_rows - 14) for i,r in enumerate(nav_data): if i < 13 or i == (num_rows - 1): continue dt = datetime.strptime(r.split(',')[0], '%d-%m-%Y') nav_line = r.split(',')[1:] nav_dict = common.get_fund_nav_dict(fund_names, nav_line) index = i - 13 for fund in fund_names: nav = nav_dict[fund] ma = ma_dict[fund][i - 13] fund_inv = inv_dict[fund] prev_inv = last_inv_dict[fund] allowed_inv = max_total_inv - fund_inv mnt_inv = get_mnt_inv(index, nav, ma, prev_inv) mnt_inv = min(mnt_inv, allowed_inv) units = mnt_inv / nav units_dict[fund] += units units_save_dict[fund].append(units) inv_dict[fund] += mnt_inv last_inv_dict[fund] = mnt_inv cf = (dt, -mnt_inv) cashflows_dict[fund].append(cf) if fund_inv + mnt_inv == max_total_inv and not stop_inv_dict[fund]: stop_inv_dict[fund] = (index + 1) last_line = nav_data[num_rows - 1].split(',') curr_dt = datetime.strptime(last_line[0], '%d-%m-%Y') curr_nav_line = last_line[1:] curr_nav_dict = common.get_fund_nav_dict(fund_names, curr_nav_line) for fund in fund_names: investment = inv_dict[fund] stop_inv = stop_inv_dict[fund] wealth = units_dict[fund] * curr_nav_dict[fund] abs_return = (wealth / investment) - 1 cf = (curr_dt, wealth) cashflows_dict[fund].append(cf) ann_return = common.xirr(cashflows_dict[fund]) stats = [investment, wealth, abs_return, ann_return, stop_inv] stats_dict[fund].extend(stats)
def run(nav_file, ma_type): nav_data = common.read_from_file(nav_file) fund_names = nav_data[0].split(',')[1:] del nav_data[1:7] ma_data = get_ma_data(nav_data) del nav_data[0:7] cashflows = common.init_array_dict(fund_names) fund_inv_dict = common.init_dict(fund_names) last_inv_dict = common.init_dict(fund_names, default_inv) returns_halfyr = common.init_array_dict(fund_names) returns_annual = common.init_array_dict(fund_names) units_dict_halfyr = common.init_dict(fund_names) units_dict_annual = common.init_dict(fund_names) units_dict_overall = common.init_dict(fund_names) cnt = len(nav_data) max_total_inv = default_inv * (cnt - 1) for i in xrange(0, cnt): row_data = nav_data[i].split(',') dt = datetime.strptime(row_data[0], '%d-%m-%Y') fund_nav = row_data[1:] fund_nav_dict = common.get_fund_nav_dict(fund_names, fund_nav) # half-yearly returns for each fund if i % 6 == 0 and i > 0: wealth = common.get_fund_wealth(fund_nav_dict, units_dict_halfyr) for fund in fund_names: cashflows_halfyr = cashflows[fund][i-6:i] # slice last 6 months cashflows if is_cashflow_missing(cashflows_halfyr): continue cf = (dt, wealth[fund]) cashflows_halfyr.append(cf) ret = common.xirr(cashflows_halfyr) returns_halfyr[fund].append(ret) # clean up for next pass units_dict_halfyr = common.init_dict(fund_names) # annual returns for each fund if i % 12 == 0 and i > 0: wealth = common.get_fund_wealth(fund_nav_dict, units_dict_annual) for fund in fund_names: cashflows_annual = cashflows[fund][i-12:i] # slice last 12 months cashflows if is_cashflow_missing(cashflows_annual): continue cf = (dt, wealth[fund]) cashflows_annual.append(cf) ret = common.xirr(cashflows_annual) returns_annual[fund].append(ret) # clean up for next pass units_dict_annual = common.init_dict(fund_names) # no investment on the last date if i == cnt - 1: break for f in fund_names: # cap total investment allowed_inv = max_total_inv - fund_inv_dict[f] prev_inv = last_inv_dict[f] nav = fund_nav_dict[f] ma = ma_data[f][i] mnt_inv = get_mnt_inv(ma_type, prev_inv, nav, ma) mnt_inv = min(mnt_inv, allowed_inv) units = mnt_inv / nav units_dict_overall[f] += units units_dict_halfyr[f] += units units_dict_annual[f] += units last_inv_dict[f] = mnt_inv fund_inv_dict[f] += mnt_inv cf = (dt, -mnt_inv) cashflows[f].append(cf) file_data = [] header_line = \ 'Fund,Investment,Wealth,Absolute Return,Annualized Return,' + \ 'Half-Yr Return Mean,Half-Yr Return Std Dev,Half-Yr Sharpe,' + \ 'Annual Return Mean,Annual Return Std Dev,Annual Sharpe' file_data.append(header_line) # final wealth nav_line = nav_data[cnt - 1].split(',')[1:] fund_nav_dict = common.get_fund_nav_dict(fund_names, nav_line) wealth = common.get_fund_wealth(fund_nav_dict, units_dict_overall) # performance stats for each fund last_date = nav_data[cnt - 1].split(',')[0] dt = datetime.strptime(last_date, '%d-%m-%Y') for fund in sorted(fund_names): fund_cashflows = cashflows[fund][:] cf = (dt, wealth[fund]) fund_cashflows.append(cf) fund_inv = fund_inv_dict[fund] abs_return = ((wealth[fund] / fund_inv) - 1) ann_return = common.xirr(fund_cashflows) hfr = returns_halfyr[fund] halfyr_rf_rate = common.get_rf_rate('half-yearly') halfyr_return_mean = numpy.mean(hfr) halfyr_return_std = numpy.std(hfr) halfyr_sharpe = common.get_sharpe_ratio(hfr, halfyr_rf_rate) afr = returns_annual[fund] annual_rf_rate = common.get_rf_rate('annual') annual_return_mean = numpy.mean(afr) annual_return_std = numpy.std(afr) annual_sharpe = common.get_sharpe_ratio(afr, annual_rf_rate) line_data = \ fund + ',' + str(fund_inv) + ',' + str(wealth[fund]) + ',' + \ str(abs_return) + ',' + str(ann_return) + ',' + \ str(halfyr_return_mean) + ',' + str(halfyr_return_std) + ',' + \ str(halfyr_sharpe) + ',' + str(annual_return_mean) + ',' + \ str(annual_return_std) + ',' + str(annual_sharpe) file_data.append(line_data) ma_file_name = 'ma_' + ma_type + '.csv' ma_file = os.path.join(data_dir, ma_file_name) common.write_to_file(ma_file, file_data)