3.新建ctp_account_info.py复制如下代码:
# encoding: UTF-8
import numpy as np
import pandas as pd
import scipy.stats as scs
import csv
from datetime import datetime
from dateutil.relativedelta import relativedelta
from time import sleep
from pyecharts.charts import (Bar,Line,Graph,Gauge,Page)#柱状图,折线图,关系图,仪表盘,多图同表
from pyecharts import options as opts
from empyrical import (sortino_ratio,omega_ratio,annual_volatility,cagr,conditional_value_at_risk,downside_risk,stability_of_timeseries,tail_ratio,value_at_risk,calmar_ratio)
#年总交易日
TRADING_DAY = 252
def output(msg):
print(f'{datetime.now()}\t{msg}')
#----------------------------------------------------------------------
def statistics_status(array):
"""返回array均值,标准差,偏度,峰度"""
stats = scs.describe(array)
return stats[2],np.sqrt(stats[3]),stats[4],stats[5]
#------------------------------------------------------------------
def plot_account(total_date:int = 0):
ctp_account_path = "C:\\ProgramData\\Anaconda3\\Lib\\site-packages\\vnpy-2.1.0-py3.7.egg\\vnpy\\app\\cta_strategy\\account_info\\ctp_account"+".csv" #ctp账户csv数据路径
df = pd.DataFrame()
account_day = [] #交易日
account_balance = [] #总资金
account_commission = [] #手续费
net_value_list = [] #净值
net_value = 0
#月度盈亏参数
last_month_date = ""
month_pnl = 0
month_dict = {}
#------------------------------------------------------------------
with open(ctp_account_path,"r",encoding="utf-8") as f1:
csvreader = csv.DictReader((line.replace("\0",'') for line in f1),delimiter=",") #line.replace移除NULL值
ctp_account = [rowdata for rowdata in csvreader]
for index in range(len(ctp_account)):
account_day.append(ctp_account[index]["datetime"]) #交易日
account_balance.append(float(ctp_account[index]["balance"]))
account_commission.append(float(ctp_account[index]["commission"]))
if total_date:
df["balance"] = account_balance[-total_date:]
df["commission"] = account_commission[-total_date:]
df["datetime"] = account_day[-total_date:]
else:
df["balance"] = account_balance
df["commission"] = account_commission
df["datetime"] = account_day
for index in range(len(df["balance"])):
if index == 0:
net_pnl = 1
else:
net_pnl = df["balance"][index]/df["balance"][index-1]-1
net_value += net_pnl
net_value_list.append((float(net_value)))
df["highlevel"] = df["balance"].rolling(min_periods=1,window=len(df),center=False).max() #净值高点
df["drawdown"] = df["balance"] - df["highlevel"] #回撤资金
df["drawdown_percent"] = (df["balance"] - df["highlevel"])/df["highlevel"] #回撤百分比
total_return = (df["balance"].values[-1]/df["balance"].values[0]-1)*100 #总收益率
total_days = len(df) / 2
annual_return = total_return / total_days * TRADING_DAY #年化收益率
max_drawdown = df["drawdown"].min() #最大回撤资金
mad_dd_percent = df["drawdown_percent"].min()*100 #最大回撤率
df["return"] = (np.log(df["balance"]) - np.log(df["balance"].shift(1))).fillna(0) #净收益率
df['net_pnl'] = df["balance"] - df["balance"].shift(1) #日盈亏
df['net_pnl'].fillna(0,inplace = True)
df.set_index("datetime",inplace=True)
#收益率均值,标准差,偏度,峰度
return_mean,return_std,return_skew, return_kurt = statistics_status(df["return"].values)
if return_std:
sharpe_ratio = df["return"].mean() * 100 / (return_std * 100) * np.sqrt(252)
else:
sharpe_ratio = 0
#sortino_info
sortino_info = sortino_ratio(df['return'])
omega_info = omega_ratio(df['return'])
#calmar_info
calmar_info = calmar_ratio(df['return'],period="yearly")
#年化波动率
annual_volatility_info = annual_volatility(df['return'])
#年化复合增长率
cagr_info = cagr(df['return'])
annual_downside_risk = downside_risk(df['return'],required_return = 0.2,period = 'yearly')
c_var = conditional_value_at_risk(df['return'])
var_info = value_at_risk(df['return'])
stability_return = stability_of_timeseries(df['return'])
#尾部比率0.25 == 1/4,收益1,风险4
tail_ratio_info = tail_ratio(df['return'])
#--------------------------------------------------------------------------------------------
output("-"*70)
output(f"账户:{ctp_account[-1]['accountid']},总资金:{float(ctp_account[-1]['balance']):,.3f},可用资金剩余:{float(ctp_account[-1]['available']):,.3f},rmb总资金:{float(ctp_account[-1]['pre_balance']):,.3f}")
output(f"总盈亏:{df['balance'].values[-1]-df['balance'].values[0]:,.3f},总收益率:{total_return:,.3f}%,复利净值:{net_value_list[-1]:,.3f}")
output(f"sharpe_ratio:\t{sharpe_ratio:,.3f}")
output(f"calmar_info:\t{calmar_info:,.3f}")
output(f"sortino_info:\t{sortino_info:,.3f}")
output(f"omega_info:\t{omega_info:,.3f}")
output(f"年化波动率:\t{annual_volatility_info:,.3f}")
output(f"年复合增长率:\t{cagr_info:,.3f}")
output(f"年化下行风险率:\t{annual_downside_risk:,.3f}")
output(f"c_var:\t{c_var:,.3f}")
output(f"var_info:\t{var_info:,.3f}")
output(f"收益稳定率:\t{stability_return:,.3f}")
output(f"尾部比率:\t{tail_ratio_info:,.3f}")
output(f"持仓盈亏:{float(ctp_account[-1]['position_profit']):,.3f}")
output(f"最大回撤率:{mad_dd_percent:,.3f}%")
output(f"收益回撤比:{-np.sum(df['net_pnl'])/max_drawdown:,.3f}")
output(f"收益率回撤率比:{-total_return/mad_dd_percent:,.3f}")
output(f"总手续费:{df['commission'].sum():,.3f}")
output(f"年化收益率:\t{annual_return:,.3f}%")
output(f"日均盈亏:{np.mean(df['net_pnl']):,.3f}\t日盈利最大值:{max(df['net_pnl']):,.3f}\t日亏损最大值:{min(df['net_pnl']):,.3f}")
output(f"日均收益率:{return_mean*100:,.3f}%,收益率标准差:{return_std*100:,.3f}%,收益率偏度:{return_skew:,.3f},收益率峰度:{return_kurt:,.3f}")
output("-"*70)
#--------------------------------------------------------------------------------------------
page = Page()
bar_1 = Line()
bar_1.add_xaxis(df['balance'].index.tolist())
bar_1.add_yaxis(f"账户:{ctp_account[-1]['accountid']}\n\n总资金\n\n起止时间:{df['balance'].index[0]}至{df['balance'].index[-1]}",df['balance'].tolist()) #主标题
bar_1.set_global_opts(opts.TitleOpts(title=f"资金\n\n总收益率:{total_return:,.3f}%"),toolbox_opts=opts.ToolboxOpts()) #副标题,ToolboxOpts设置工具箱配置项
bar_1.set_series_opts(label_opts=opts.LabelOpts(is_show=False)) #系列配置项
bar_2 = Bar()
bar_2.add_xaxis(df.index.tolist())
bar_2.add_yaxis(f"复利净值最高点:{max(net_value_list):,.3f}\t复利净值最低点:{min(net_value_list):,.3f}",net_value_list) #主标题
bar_2.set_global_opts(opts.TitleOpts(title="复利净值"),toolbox_opts=opts.ToolboxOpts()) #副标题,ToolboxOpts设置工具箱配置项
bar_2.set_series_opts(label_opts=opts.LabelOpts(is_show=False)) #系列配置项
bar_3 = Bar()
bar_3.add_xaxis(df.index[1:].tolist())
bar_3.add_yaxis(f"日盈利最大值:{max(df['net_pnl']):,.3f}\n\n日亏损最大值:{min(df['net_pnl']):,.3f}",df['net_pnl'].tolist()) #主标题
bar_3.set_global_opts(opts.TitleOpts(title="日收益"),toolbox_opts=opts.ToolboxOpts()) #副标题,ToolboxOpts设置工具箱配置项
bar_3.set_series_opts(label_opts=opts.LabelOpts(is_show=False)) #系列配置项
for pnl_index in df['net_pnl'].index:
month_date = pnl_index[:7]
if not isinstance(df['net_pnl'][pnl_index],np.float64):
continue
if month_date == last_month_date:
month_pnl += df['net_pnl'][pnl_index]
else:
#月份减一保存实际月份收益
month_dict.update({month_date:month_pnl})
for key,value in list(month_dict.items()):
if isinstance(key,datetime):
continue
key = datetime.strptime(key,"%Y-%m") - relativedelta(months = 1)
month_dict.update({key:value})
#month_dict删除原始的str键值对
for key,value in list(month_dict.items()):
if isinstance(key,str):
month_dict.pop(key)
month_pnl = df['net_pnl'][pnl_index]
last_month_date = month_date
month_dict.pop(list(month_dict.keys())[0])
#兼容月度数据不足
try:
max_month_pnl = max(month_dict.values())
min_month_pnl = min(min(month_dict.values()),0)
except ValueError:
max_month_pnl = 0
min_month_pnl = 0
bar_4 = Bar()
bar_4.add_xaxis(list(month_dict.keys()))
bar_4.add_yaxis(f"月盈亏\n\n最大月盈利:{max_month_pnl:,.3f}\n\n最大月亏损:{min_month_pnl:,.3f}",list(month_dict.values()))
bar_4.set_global_opts(opts.TitleOpts(title="月盈亏"),toolbox_opts=opts.ToolboxOpts()) #设置工具箱配置项
bar_4.set_series_opts(label_opts=opts.LabelOpts(is_show=False)
) #系列配置项
bar_5 = Bar()
bar_5.add_xaxis(df["drawdown"].index.tolist())
bar_5.add_yaxis(f"回撤资金\n\n最大回撤资金:{max_drawdown:,.3f}",df["drawdown"].tolist()) #主标题
bar_5.set_global_opts(opts.TitleOpts(title="资金"),toolbox_opts=opts.ToolboxOpts()) #副标题,ToolboxOpts设置工具箱配置项
bar_5.set_series_opts(label_opts=opts.LabelOpts(is_show=False)) #系列配置项
bar_6 = Bar()
bar_6.add_xaxis(df["drawdown_percent"].index.tolist())
bar_6.add_yaxis(f"回撤百分比\n\n最大回撤率:{mad_dd_percent:,.3f}%",df["drawdown_percent"].tolist()) #主标题
bar_6.set_global_opts(opts.TitleOpts(title="回撤百分比"),toolbox_opts=opts.ToolboxOpts()) #副标题,ToolboxOpts设置工具箱配置项
bar_6.set_series_opts(label_opts=opts.LabelOpts(is_show=False)) #系列配置项
hist,bin_edges= np.histogram(df['net_pnl'], bins=50)
bar_7 = Bar()
bar_7.add_xaxis(bin_edges[1:].tolist())
bar_7.add_yaxis("日盈亏分布直方图",hist.tolist()) #主标题
bar_7.set_global_opts(opts.TitleOpts(title="频数"),toolbox_opts=opts.ToolboxOpts()) #副标题,ToolboxOpts设置工具箱配置项
bar_7.set_series_opts(label_opts=opts.LabelOpts(is_show=False)) #系列配置项
bar_8 = Bar()
bar_8.add_xaxis(df.index.tolist())
bar_8.add_yaxis(f"日最高手续费:{df['commission'].max()}",df["commission"].tolist()) #主标题
bar_8.set_global_opts(opts.TitleOpts(title="手续费"),toolbox_opts=opts.ToolboxOpts()) #副标题,ToolboxOpts设置工具箱配置项
bar_8.set_series_opts(label_opts=opts.LabelOpts(is_show=False)) #系列配置项
page.add(bar_1)
page.add(bar_2)
page.add(bar_3)
page.add(bar_4)
page.add(bar_5)
page.add(bar_6)
page.add(bar_7)
page.add(bar_8)
page.render(ctp_account_path.replace(".csv",".html"))#保存为html
#--------------------------------------------------------------------------------------------
if __name__ == '__main__':
while True:
plot_account(total_date=360)#统计最近total_date日数据
sleep(60)
break