
用且慢小账本很久了,在其上也积累了不少数据,大体思路清晰简单,不过数据不能导出,合并以及定制的分析不好做。
正好最近在梳理可转债双低策略,正好做了其中部分功能,感觉重合度比较高,顺便就把这块的功能梳理一下,汇集成一个更对个人更好用的工具。
以后这方面的需求用自建的工具为主了,目标是协助记录净值法的投资收益,先展示一下结果,后面附上代码。

实现主要关注的功能:
- 使用简单,就三个操作:初始化、转账、记录总金额
- 输出格式可控,有注意格式化方面的优化
- 除了基础数据,还可以计算份额变化、累计投入、收益/损失情况
- 在有历史数据的情况下,可以用于把指数标的还原为净值法的表达,方便做对比
- 稍加封装,可以方便汇总多个账户的数据
- 计算出的数据也比较合适放到数据库,后续就可以用BI软件来做更细致的分析和展示
- 输入这里做些简单封装,就可以包装成更实用的GUI工具,方便用户操作
- 数据都在方便,后续操作更便捷
- 功能和且慢小账本基本等价
- 如果包装成saas服务,后续会方便做二次开发
- 输出的格式还可以考虑做成excel,方便展示和分享
python本身的准备就略过了,主要是安装依赖pip instlal pandas
。下面展示实际的简版代码例子,可以完成基本功能,限于篇幅扩展功能不在这里展示。
import pandas as pd
class NetValueInvestPlan2:
"""
净值交易策略
"""
def __init__(self, start_date, amount, data_format={'净值': "{:.4f}", '总资产': "{:,.0f}", '总份额': "{:,.0f}", '资金变动': "{:,.0f}", '份额变动': "{:,.0f}", '期间累计投入': "{:,.0f}", '绝对损失': "{:.2%}"}):
self.start_date = start_date
self.initial_amount = amount
self.data_format = data_format
self.amount_data = []
self.transfer_data = []
def record_value(self, date, amount, moneyinout=0.0):
self.amount_data.append({"日期":date, "总资产":amount})
if moneyinout!=0.0:
self.money_transfer(date, moneyinout)
def money_transfer(self, date, moneyinout):
self.transfer_data.append({"日期":date, "转账":moneyinout})
def compute_table(self):
headers="""日期 净值 总资产 总份额 资金变动 份额变动 期间累计投入 绝对损失""".strip().split()
d = """{0} 1.00 {1} {1} {1} {1} {1} 0.0""".format(self.start_date, self.initial_amount)
self.df = pd.DataFrame([dict(zip(headers, i.split())) for i in d.strip().splitlines()])
self.df.set_index("日期", inplace=True)
self.df = self.df[headers[1:]]
# self.df.sort_index(inplace=True)
for col in headers[1:]:
self.df[col] = pd.to_numeric(self.df[col], errors='coerce')
for d in self.amount_data:
self.df.loc[d["日期"]] = [0.0, d["总资产"], 0.0, 0.0, 0.0, 0.0, 0.0]
for d in self.transfer_data:
if d["日期"] in self.df.index:
self.df.loc[d["日期"]]["资金变动"] = d["转账"]
else:
pre_amount = self.df.iloc[self.df.index.get_loc(d["日期"])-1]["总资产"]
self.df.loc[d["日期"]] = [0.0, pre_amount + d["转账"], 0.0, d["转账"], 0.0, 0.0, 0.0]
self.df['期间累计投入'] = self.df['资金变动'].cumsum()
for i, row in self.df.iterrows():
if i != self.start_date:
cur = self.df.loc[i]
pre = self.df.iloc[self.df.index.get_loc(i)-1]
cur['份额变动'] = cur['资金变动'] / pre['净值']
cur['总份额'] = cur['份额变动'] + pre['总份额']
cur['净值'] = cur['总资产'] / cur['总份额']
cur['绝对损失'] = cur['总资产'] / cur['期间累计投入'] - 1
def output(self):
return (self.df.style.format(self.data_format))
p = NetValueInvestPlan2("2020-07-07", 120000.0)
p.record_value('2020-07-10', 120057.71)
p.record_value('2020-07-28', 119405.73)
p.record_value('2020-07-29', 120233.33)
p.money_transfer('2020-07-30', 10003.0)
p.compute_table()
p.output()
Reference
- 集思路里的双低可转债策略
- 雪球大V关于基金净值的计算方法讨论