公司:爱玩特智能
岗位:量化研究员
时间:2022年10月17号,线下开卷笔试
1 题目
笔试说明
1、编程要求
语言:Python
结果汇总至Excel,表一至表五
代码分块汇总至一个python文件、要求注释完整
2、数据说明
数据库链接:bj-cdb-3gfxha84.sql.tencentcdb.com
端口号:59970
账号:test1
密码:ainvest_test1
库名:test
表名:account_balance
数据结构:
As_Of_Date:日期
Position_amount:股票总金额
Cash:现金金额
Total_account:账户总金额(账户总金额=股票总金额+现金总金额)
ID:用户编号
3、考题
1)连接数据库,读取指定数据
2)画出时间-用户数的走势图
3)计算每个用户每天的投资回报率。
投资回报率=今天账户总金额/昨日账户总金额-1
4)计算每个用户每天的累计回报率
累计回报率 = +1)
5)计算描述性统计——所有用户的年化回报率,年化波动率和夏普比率。指出夏普比率最高和最低的用户分别是谁
年化回报率=日回报率平均值252天
年化波动率=日回报率的标准差根号下252
夏普比率=年化回报率/年化波动率
6)简单线性回归
将样本按照时间分为前95%和后5%。写出前95%的最后一天日期和后5%最后一天日期。
计算每个用户在前95%样本中的年化回报率,定义为X;以及后5%样本中的年化回报率,定义为y
做y对x的线性回归,保留常数项。判断两者相关性是否显著,正相关还是负相关。
2 python代码实现
由本人自己理解并实现,并不一定正确,也不是答案,我提供的代码仅供参考
import pymysql
import pandas as pd
import matplotlib.pyplot as plt
from functools import reduce
import numpy as np
import statsmodels.api as sm
# 问题(1):连接数据库
conn = pymysql.Connect(
host = 'bj-cdb-3gfxha84.sql.tencentcdb.com',
port = 59970,
user = 'root',
passwd = 'ainvest_test1',
db = 'test',
charset = 'utf8'
)
# 问题(2)画出时间-用户数的走势图
sql = 'SELECT * FROM account_balance;'
data = pd.read_sql(sql, conn)
time_user_number_dict =dict(data.As_Of_Date.value_counts())
time_user_number = sorted(time_user_number_dict.items(), key=lambda item:item[0])
x = range(len(time_user_number))
y = list(dict(time_user_number).values())
plt.plot(x,y,'s-',color = 'r')#s-:方形
plt.xlabel("As_Of_Date")#横坐标名字
plt.ylabel("numbers")#纵坐标名字
plt.show()
# 问题(3)计算每个用户每天的投资回报率。
sql = 'SELECT As_Of_Date,ID,Total_account FROM account_balance;'
data_history = pd.read_sql(sql, conn)
user_list = list(set(data_history.ID))
user_return_rate = {}
for user in user_list:
user_data = data_history[data_history['ID'] ==user]
# 按时间排序
user_data.sort_values(by='As_Of_Date')
# 计算投资回报率:(后一行的总金额/前一行的总金额)-1
return_rate =list((user_data['Total_account'].shift(periods=-1, axis=0)/user_data['Total_account']).apply(lambda x: x-1))
# 按时间顺序存储每个用户每天的投资回报率
user_return_rate[user] = return_rate[:-1]
# 问题(4)计算每个用户每天的累计回报率
for user,rate_list in user_return_rate.items():
# 累计回报率:每天的回报率+1后,再全部求乘积
reduce_rate = reduce(lambda x,y:x*y,[x+1 for x in rate_list ])
print('用户ID{}的累计回报率为={}'.format(user,reduce_rate))
# 问题(5)计算描述性统计
# 年华回报率
sharpe_ratio_dict = {}
for user,rate_list in user_return_rate.items():
# 年化回报率
year_return_rate = np.mean(rate_list)*252
# 年化波动率
year_volatility = np.std(rate_list,ddof=1)* np.sqrt(252)
# 夏普比率
sharpe_ratio = year_return_rate/year_volatility
sharpe_ratio_dict[user] = sharpe_ratio
# 输出夏普比率最高和最低的用户
sharpe_ratio_dict_sorted= dict(sorted(sharpe_ratio_dict.items(), key=lambda item:item[1]))
print('夏普比率最低的用户是{},夏普比率为{}'.format(list(sharpe_ratio_dict_sorted.keys())[0],list(sharpe_ratio_dict_sorted.values())[0]))
print('夏普比率最高的用户是{},夏普比率为{}'.format(list(sharpe_ratio_dict_sorted.keys())[-1],list(sharpe_ratio_dict_sorted.values())[-1]))
# 问题(6)简单线性回归
# 输出前95%的最后一天日期和后5%最后一天日期。
user_data = data_history[data_history['ID'] ==user_list[0]]
# 按时间排序
user_data.sort_values(by='As_Of_Date')
# 前95%的数据跨度天数
data_len = int(len(rate_list)*0.95)
print('前95%的最后一天日期是{}'.format(user_data['As_Of_Date'].iloc[data_len-1]))
print('后5%的最后一天日期是{}'.format(user_data['As_Of_Date'].iloc[len(user_data)-1]))
X = []
Y = []
for user,rate_list in user_return_rate.items():
# 第一步计算样本前95%的年化回报率
x_year_return_rate = np.mean(rate_list[:data_len])*252
# 第二步计算样本后5%的年化回报率
y_year_return_rate = np.mean(rate_list[data_len+1:])*252
X.append(x_year_return_rate)
Y.append(y_year_return_rate)
# 第三步,线性回归分析
X = sm.add_constant(X) # 若模型中有截距,必须有这一步
model = sm.OLS(Y, X).fit() # 构建最小二乘模型并拟合
print(model.summary()) # 输出回归结果
conn.close()
Word题目、本人撰写的文档介绍及代码,见github
https://github.com/BetterBench/Quantitative\_research\_document