def xirrcal(cftable, trades, date, guess=0.1): """ calculate the xirr rate :param cftable: cftable (pd.Dateframe) with date and cash column :param trades: list [trade1, ...], every item is an trade object, whose shares would be sold out virtually :param date: string of date or datetime object, the date when virtually all holding positions being sold :param guess: floating number, a guess at the xirr rate solution to be used as a starting point for the numerical solution :returns: the IRR as a single floating number """ date = convert_date(date) partcftb = cftable[cftable["date"] <= date] if len(partcftb) == 0: return 0 cashflow = [(row["date"], row["cash"]) for i, row in partcftb.iterrows()] rede = 0 for fund in trades: if not isinstance(fund, itrade): rede += fund.aim.shuhui( fund.briefdailyreport(date).get("currentshare", 0), date, fund.remtable[fund.remtable["date"] <= date].iloc[-1].rem, )[1] else: # 场内交易 pricedf = get_daily(fund.code, end=date.strftime("%Y%m%d"), prev=20) price = pricedf[pricedf.date <= date].iloc[-1]["close"] rede += fund.cftable.share.sum() * price cashflow.append((date, rede)) return xirr(cashflow, guess)
def xirrcal(cftable, trades, date, guess): ''' calculate the xirr rate :param cftable: cftable (pd.Dateframe) with date and cash column :param trades: list [trade1, ...], every item is an trade object, whose shares would be sold out virtually :param date: string of date or datetime object, the date when virtually all holding positions being sold :param guess: floating number, a guess at the xirr rate solution to be used as a starting point for the numerical solution :returns: the IRR as a single floating number ''' date = convert_date(date) partcftb = cftable[cftable['date'] <= date] if len(partcftb) == 0: return 0 cashflow = [(row['date'], row['cash']) for i, row in partcftb.iterrows()] rede = 0 for fund in trades: rede += fund.aim.shuhui( fund.briefdailyreport(date).get('currentshare', 0), date, fund.remtable[fund.remtable['date'] <= date].iloc[-1].rem)[1] cashflow.append((date, rede)) return xirr(cashflow, guess)
def xirrcal(cftable, trades, date, startdate=None, guess=0.01): """ calculate the xirr rate :param cftable: cftable (pd.Dateframe) with date and cash column :param trades: list [trade1, ...], every item is an trade object, whose shares would be sold out virtually :param date: string of date or datetime object, the date when virtually all holding positions being sold :param guess: floating number, a guess at the xirr rate solution to be used as a starting point for the numerical solution :returns: the IRR as a single floating number """ date = convert_date(date) partcftb = cftable[cftable["date"] <= date] if len(partcftb) == 0: return 0 if not startdate: cashflow = [(row["date"], row["cash"]) for i, row in partcftb.iterrows()] else: if not isinstance(startdate, dt.datetime): startdate = dt.datetime.strptime( startdate.replace("-", "").replace("/", ""), "%Y%m%d") start_cash = 0 for fund in trades: start_cash += fund.briefdailyreport(startdate).get( "currentvalue", 0) cashflow = [(startdate, -start_cash)] partcftb = partcftb[partcftb["date"] > startdate] cashflow.extend([(row["date"], row["cash"]) for i, row in partcftb.iterrows()]) rede = 0 for fund in trades: if not isinstance(fund, itrade): partremtb = fund.remtable[fund.remtable["date"] <= date] if len(partremtb) > 0: rem = partremtb.iloc[-1]["rem"] else: rem = [] rede += fund.aim.shuhui( fund.briefdailyreport(date).get("currentshare", 0), date, rem)[1] else: # 场内交易 rede += fund.briefdailyreport(date).get("currentvalue", 0) cashflow.append((date, rede)) return xirr(cashflow, guess)
def cb_ytm(issue_date, rlist, cp, date=None, tax=1.0, guess=0.01): """ 可转债到期收益率计算器 :param issue_date: 发行日期 :param rlist: 计息及赎回列表 :param cp: 可转债现价 :param date: 参考日期 :param tax: 计税 1 vs 0.8 税后 YTM :param guess: YTM 估计初始值 :return: """ if rlist[-1] < 100: logger.warning( "the format of rlist must contain the final return more than 100 without interest of that year" ) issue_date = issue_date.replace("-", "").replace("/", "") issue_date_obj = dt.datetime.strptime(issue_date, "%Y%m%d") if date is None: date_obj = dt.datetime.today() else: date = date.replace("-", "").replace("/", "") date_obj = dt.datetime.strptime(date, "%Y%m%d") cf = [(date_obj, -cp)] passed = (date_obj - issue_date_obj).days // 365 for i, r in enumerate(rlist[:-1]): if i >= passed: cf.append( (issue_date_obj + dt.timedelta(days=(i + 1) * 365), r * tax)) # 关于赎回利息计算: https://www.jisilu.cn/?/question/339 # https://www.jisilu.cn/question/5807 # 富投网的算法:将最后一年超出100的部分,全部按照20%计税, cf.append((issue_date_obj + dt.timedelta(days=(len(rlist) - 1) * 365), rlist[-1])) # print(cf) return xirr(cf, guess=guess)