打造自己的基金工具-基金小助手

451 阅读4分钟

前言

续接上篇,上篇完成了一个收集基金净值的功能模块,本篇再次基础上进行包装,产出一个可用的基金助手

实现

在获取到基金的昨日收盘净值、当天实时净值估算等数据后,据此就可以计算出我们所关心的数据了。 分两种情况,有持仓和未持仓(关注)基金。

有持仓的则根据自己的持仓情况配置(持仓成本价+持仓成本金额或持仓成本价+持仓份额),然后就可以查看当天盈亏、涨跌幅以及估算等基金数据了。

没有持仓的可以按持仓数为0配置,也可以直接配置到列表,如此可以持续关注表现。

为支持配置,设计配置项如下:

{
  "data_update_timespan": 300,
  "myfunds": [
    {
      "code": "006229",
      "price": 2.1514,
      "amount": 0.00,
      "cost": 18620
    },
    {
      "code": "012414",
      "price": 0.00,
      "amount": 0.00,
      "cost": 0
    }
  ],
  "monitors": ["005669", "000689", "001933"]
}

其中:

  • data_update_timespan:刷新基金数据的时间间隔,单位为秒;
  • myfunds:我的持仓基金数据
    • code:基金代码
    • price:持仓成本价
    • amount:持仓份额
    • cost:持仓金额
  • monitors:关注的基金列表

设计创建一个子线程定时去更新基金数据,主线程支持update刷新基金数据,并支持命令行指令。

为了显示美观,支持红绿色,引入prettytable表格显示数据,引入colorama支持红绿色,红涨绿跌。

基金代码前的*表示持仓基金,且最后一行为持仓数据汇总。

助手代码

# coding : utf-8
import threading
import time
import sys
import json
import os
import datetime
import fund_info
import colorama
from prettytable import PrettyTable


def get_fund_info(fund):
    """
    获取基金信息
    :param fund: 基金配置
    :return: 基金对象
    """
    try:
        code = fund['code']
        if 'cost' in fund and float(fund['cost']) >= 0.01:
            info = fund_info.FundInfo.get_info_with_cost(code, fund['price'], fund['cost'])
        else:
            info = fund_info.FundInfo.get_info_with_amount(code, fund['price'], fund['amount'])
        return info
    except Exception as e:
        print('获取基金异常', Exception, e)
        return None


def bk_update_info(config, run_flag=False, wait=1):
    """
    定时刷新基金详情信息
    :param wait:
    :param config:
    :param run_flag:
    :return:
    """
    funds = config['myfunds']
    wait = config['data_update_timespan']
    tab = PrettyTable()
    tab.field_names = ['序号', '基金代码', '基金名称', '日涨跌幅', '今日盈亏', '净值估算', '基金净值', '总盈亏估算', '收益率估算',
                       '持仓市值', '持仓盈亏', '总收益率', '持仓成本', '持仓金额', '持仓份额', '更新时间']
    colorama.init(autoreset=True)
    while True:
        # 更新信息
        infos = []
        for fc in funds:
            fund = get_fund_info(fc)
            if fund is None:
                continue
            infos.append(fund.info)

        # 添加汇总信息
        if len(infos) > 0:
            total = {}
            for k, v in infos[-1].items():
                total[k] = '-'
            total['基金代码'] = '*'*6
            total['基金名称'] = '汇总'
            total['今日盈亏'] = 0.0
            total['持仓盈亏'] = 0.0
            total['持仓市值'] = 0.0
            total['持仓金额'] = 0.0
            total['持仓金额'] = 0.0
            total['总盈亏估算'] = 0.0
            total['持仓成本'] = '-'
            total['日涨跌幅'] = '0.00'
            total['更新时间'] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M")
            for info in infos:
                total['今日盈亏'] += float(info['今日盈亏'])
                total['持仓盈亏'] += float(info['持仓盈亏'])
                total['总盈亏估算'] += float(info['总盈亏估算'])
                total['持仓市值'] += float(info['持仓市值'])
                total['持仓金额'] += float(info['持仓金额'])
            if abs(total['持仓盈亏']) > 0.00001:
                total['总收益率'] = '{0:.4f}'.format(100 * total['持仓盈亏'] / total['持仓金额'])
                total['收益率估算'] = '{0:.4f}'.format(total['总盈亏估算'] * 100 / total['持仓金额'])
            infos.append(total)

        # 组装显示信息
        i = 0
        tab.clear_rows()
        for info in infos:
            i += 1
            row = [str(i)]
            # 我的基金
            if float(info['持仓市值']) > 0.00001:
                info['基金代码'] = '*' + info['基金代码']
            # 字段处理
            for field in tab.field_names[1:]:
                if field in info:
                    row.append(info[field])
                else:
                    row.append('-')
            # 设置基金红绿颜色
            if float(info['日涨跌幅']) > 0.0 or float(info['今日盈亏']) > 0.0:
                row[0] = colorama.Fore.RED + row[0]
            elif float(info['日涨跌幅']) < 0.0 or float(info['今日盈亏']) < 0.0:
                row[0] = colorama.Fore.GREEN + row[0]
            row[-1] += colorama.Fore.RESET + colorama.Back.RESET + colorama.Style.RESET_ALL
            tab.add_row(row)

        # 显示信息
        os.system('cls')
        print(tab, end='\n>')
        if not run_flag:
            break
        time.sleep(wait)


if __name__ == '__main__':
    # 基金配置
    config = {
        "data_update_timespan": 300,
        "myfunds": [
            {
                "code": "006229",
                "price": 2.4514,
                "amount": 0.00,
                "cost": 250000
            },
            {
                "code": "012414",
                "price": 0.00,
                "amount": 0.00,
                "cost": 0
            }
        ]
    }
    argv = sys.argv
    if len(argv) > 1:
        with open(argv[1]) as fd:
            config = json.load(fd)
    run_flag = True

    # 配置特殊处理
    funds = config['myfunds']
    if 'monitors' in config and len(config['monitors']) > 0:
        for fund in config['monitors']:
            funds.append({'code': fund, 'price': 0.0, 'amount': 0.0, 'cost': 0.0})

    # 获取数据线程
    wait = config['data_update_timespan']
    bk = threading.Thread(target=bk_update_info, args=(config, run_flag, wait))
    bk.start()

    time.sleep(1)
    while True:
        option = input('>')
        if option == 'update':
            bk_update_info(config)
        elif option == 'quit':
            run_flag = False
        else:
            try:
                os.system(option)
            except Exception as e:
                print('异常', Exception, e)

效果

+------+----------+--------------------------+----------+------------+----------+----------+------------+------------+-------------+------------+----------+----------+----------+----------+------------------+
| 序号 | 基金代码 |         基金名称         | 日涨跌幅 |  今日盈亏  | 净值估算 | 基金净值 | 总盈亏估算 | 收益率估算 |   持仓市值  |  持仓盈亏  | 总收益率 | 持仓成本 | 持仓金额 | 持仓份额 |     更新时间     |
+------+----------+--------------------------+----------+------------+----------+----------+------------+------------+-------------+------------+----------+----------+----------+----------+------------------+
|  1   | *006229  |    中欧医疗创新股票C     |  -1.21   | -1887.3772 |  2.2302  |  2.2576  | 73621.4878 |  92.0269   | 155508.8611 | 75508.8650 | 94.3861  |  1.1614  | 80000.00 | 68882.38 | 2021-12-24 15:00 |
|  2   |  012414  |  招商中证白酒指数(LOF)C  |   0.52   |   0.0000   |  1.4162  |  1.4088  |   0.0000   |     -      |    0.0000   |   0.0000   |  0.0000  |  0.0000  |   0.00   |   0.00   | 2021-12-24 15:00 |
|  3   |  005669  |   前海开源公用事业股票   |  -1.64   |   0.0000   |  3.6775  |  3.7387  |   0.0000   |     -      |    0.0000   |   0.0000   |  0.0000  |  0.0000  |   0.00   |   0.00   | 2021-12-24 15:00 |
|  4   |  000689  |   前海开源新经济混合A    |  -3.52   |   0.0000   |  3.4593  |  3.5854  |   0.0000   |     -      |    0.0000   |   0.0000   |  0.0000  |  0.0000  |   0.00   |   0.00   | 2021-12-24 15:00 |
|  5   |  001933  |     华商新兴活力混合     |  -3.41   |   0.0000   |  2.8679  |  2.9690  |   0.0000   |     -      |    0.0000   |   0.0000   |  0.0000  |  0.0000  |   0.00   |   0.00   | 2021-12-24 15:00 |
|  6   |  001822  | 华商智能生活灵活配置混合 |  -3.62   |   0.0000   |  2.9944  |  3.1070  |   0.0000   |     -      |    0.0000   |   0.0000   |  0.0000  |  0.0000  |   0.00   |   0.00   | 2021-12-24 15:00 |
|  7   |  001704  | 国投瑞银进宝灵活配置混合 |  -4.13   |   0.0000   |  4.2885  |  4.4732  |   0.0000   |     -      |    0.0000   |   0.0000   |  0.0000  |  0.0000  |   0.00   |   0.00   | 2021-12-24 15:00 |
|  8   | *******  |           汇总           |   0.00   | -1887.3772 |    -     |    -     | 73621.4878 |  92.0269   | 155508.8611 | 75508.865  | 94.3861  |    -     | 80000.0  |    -     | 2021-12-24 15:38 |
+------+----------+--------------------------+----------+------------+----------+----------+------------+------------+-------------+------------+----------+----------+----------+----------+------------------+

image.png