File size: 9,162 Bytes
7ec53ba |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
import math
import choose
import pandas as pd
import os
import datetime
from pymongo import MongoClient
client = MongoClient(
"mongodb://wth000:wth000@43.159.47.250:27017/dbname?authSource=wth000")
db = client["wth000"]
# names = ["可转债","COIN", "股票", "指数", "行业", "ETF",]
names = ["股票",]
moneyused = 0.9 # 设置资金利用率
# 获取当前.py文件的绝对路径
file_path = os.path.abspath(__file__)
# 获取当前.py文件所在目录的路径
dir_path = os.path.dirname(file_path)
# 获取当前.py文件所在目录的上两级目录的路径
dir_path = os.path.dirname(os.path.dirname(dir_path))
files = os.listdir(dir_path)
for file in files:
for filename in names:
if (filename in file):
try:
# 获取文件名和扩展名
name, extension = os.path.splitext(file)
path = os.path.join(dir_path, f"{name}.csv")
df = pd.read_csv(path)
watchtime = 1999
if ("股票" in name) and ("可转债" not in name): # 数据截取
watchtime = 2014
start_date = datetime.datetime(watchtime, int(
1), int(1)).strftime("%Y-%m-%d %H:%M:%S")
end_date = datetime.datetime(datetime.datetime.strptime(
start_date, "%Y-%m-%d %H:%M:%S").year + 8, int(1), int(1)).strftime("%Y-%m-%d %H:%M:%S")
df = df[(df["日期"] >= start_date) & (df["日期"] <= end_date)]
# else: # 数据截取
# watchtime = 2021
# start_date = datetime.datetime(
# watchtime, int(1), int(1)).strftime("%Y-%m-%d %H:%M:%S")
# end_date = datetime.datetime(datetime.datetime.strptime(
# start_date, "%Y-%m-%d %H:%M:%S").year + 8, int(1), int(1)).strftime("%Y-%m-%d %H:%M:%S")
# df = df[df["日期"] >= start_date]
# df = df[df["日期"] <= end_date]
df = df.sort_values(by="日期") # 以日期列为索引,避免计算错误
dates = df["日期"].copy().drop_duplicates().tolist() # 获取所有不重复日期
df = df.groupby("代码", group_keys=False).apply(
choose.technology)
df, m, n = choose.choose("交易", name, df)
if ("股票" in name):
for i in range(1, n+1):
df = df[df[f"{i}日后总涨跌幅(未来函数)"] <= 3*(1+0.1*n)]
else:
for i in range(1, n+1):
df = df[df[f"{i}日后总涨跌幅(未来函数)"] <= 20*(1+0.1*n)]
trade_path = os.path.join(os.path.abspath("."), "资产交易细节")
if not os.path.exists(trade_path):
os.makedirs(trade_path)
df.to_csv(f"{trade_path}/{name}周期{n}交易细节.csv", index=False)
print("交易细节已输出")
result_df = pd.DataFrame({})
for i in range(1, n+1):
# 持有n天则掉仓周期为n,实际上资金实盘当中是单独留一份备用金补给亏的多的日期以及资金周转
days = dates[i::n+1]
daydf = df[df["日期"].isin(days)]
# tradedaypath = os.path.join(os.path.abspath("."), "资产分组交易细节")
# if not os.path.exists(tradedaypath):
# os.makedirs(tradedaypath)
# daydf.to_csv(f"{tradedaypath}/{name}周期{i}交易细节.csv", index=False)
result = []
cash_balance = 1 # 初始资金设置为1元
twocash_balance = 1
# 每份资金的收益率
for date, group in daydf.groupby("日期"):
daily_cash_balance = {} # 用于记录每日的资金余额
if not group.empty: # 如果当日没有入选标的,则收益率为0
for x in range(1, n+1):
if x < n:
group_return = (
(group[f"{x}日后总涨跌幅(未来函数)"]).mean() + 1) # 计算平均收益率
if x == n:
group_return = group_return*(1-m)
# 复投累计收益率
cash_balance *= (group_return-1) * \
moneyused+1
# 不复投累计收益率
twocash_balance += (group_return-1) * \
moneyused
daily_cash_balance[f"未来{x}日盘中资产收益"] = group_return
daily_cash_balance[f"下周期余额复投"] = cash_balance
daily_cash_balance[f"下周期余额不复投"] = twocash_balance
result.append(
{"日期": date, f"第{i}份资金盘中资产收益": daily_cash_balance})
result_df = pd.concat([result_df, pd.DataFrame(result)])
manyday = pd.DataFrame({"日期": dates})
manyday = manyday[~manyday["日期"].isin(df["日期"])]
# 将两个数据集根据key列进行合并
result_df = pd.concat([result_df, manyday])
result_df = result_df.sort_values(
by="日期").reset_index(drop=True)
for i in range(1, n+1): # 对每一份资金列分别根据对应的数据向下填充数据
cash = 1
twocash = 1
daysindex = result_df[result_df[f"第{i}份资金盘中资产收益"].notna()].copy()[
"日期"]
for dayindex in daysindex:
fill = result_df[result_df["日期"]
== dayindex][f"第{i}份资金盘中资产收益"]
for col, val in fill.items():
for x, (colnum, value) in enumerate(val.items()):
if x < n:
# print(col, val, colnum, value)
result_df.at[col+x+1,
f"第{i}份资金周期资产收益"] = value
result_df.at[col+x+1,
f"第{i}份资金累积资产收益复投"] = value*cash
result_df.at[col+x+1,
f"第{i}份资金累积资产收益不复投"] = value*twocash
if x == n:
nextcash = value
cash = nextcash
if x == n+1:
twonextcash = value
twocash = twonextcash
for i in range(1, n+1): # 对每一份资金列分别根据对应的数据向下填充数据
result_df[f"第{i}份资金周期资产收益"] = result_df[f"第{i}份资金周期资产收益"].fillna(
1)
result_df[f"第{i}份资金累积资产收益复投"] = result_df[f"第{i}份资金累积资产收益复投"].fillna(
method="ffill").fillna(1)
result_df[f"第{i}份资金累积资产收益不复投"] = result_df[f"第{i}份资金累积资产收益不复投"].fillna(
method="ffill").fillna(1)
# 使用 filter() 方法选择所有包含指定子字符串的列
retrade = result_df.filter(like="资金累积资产收益复投").columns
result_df["总资产收益率(复投)%"] = (
result_df[retrade].mean(axis=1)-1)*100
notretrade = result_df.filter(like="资金累积资产收益不复投").columns
result_df["总资产收益率(不复投)%"] = (
result_df[notretrade].mean(axis=1)-1)*100
print("持仓周期", n, "复投收益率", result_df["总资产收益率(复投)%"])
result_df["日期"] = result_df["日期"].str.replace('-', '||')
# 新建涨跌分布文件夹在上级菜单下,并保存结果
path = os.path.join(os.path.abspath("."), "资产变动")
if not os.path.exists(path):
os.makedirs(path)
result_df.to_csv(
f"{path}/{name}持有{n}日{str(watchtime)}年真实收益.csv", index=False)
print("任务已经完成!")
except Exception as e:
print(f"发生bug: {e}")
|