235 lines
7.7 KiB
Python
Executable File
235 lines
7.7 KiB
Python
Executable File
import numpy as np
|
||
import akshare as ak
|
||
import os
|
||
from datetime import datetime, timedelta
|
||
import pandas as pd
|
||
import mplfinance as mpf
|
||
|
||
def CalTrueFluc(data, day):
|
||
|
||
H_L = data.iloc[day]['最高'] - data.iloc[day]['最低']
|
||
H_PDC = data.iloc[day]['最高'] - data.iloc[day-1]['收盘']
|
||
PDC_L = data.iloc[day-1]['收盘'] - data.iloc[day]['最低']
|
||
TrueFluc = np.max([H_L, H_PDC, PDC_L])
|
||
print('high', data.iloc[day]['最高'], 'low', data.iloc[day]['最低'], 'TrueRange', TrueFluc)
|
||
|
||
return TrueFluc
|
||
|
||
def calc_sma_atr_pd(kdf,period):
|
||
"""计算TR与ATR
|
||
|
||
Args:
|
||
kdf (_type_): 历史数据
|
||
period (_type_): ATR周期
|
||
|
||
Returns:
|
||
_type_: 返回kdf,增加TR与ATR列
|
||
"""
|
||
kdf['HL'] = kdf['最高'] - kdf['最低']
|
||
kdf['HC'] = np.abs(kdf['最高'] - kdf['收盘'].shift(1))
|
||
kdf['LC'] = np.abs(kdf['最低'] - kdf['收盘'].shift(1))
|
||
kdf['TR'] = np.round(kdf[['HL','HC','LC']].max(axis=1), 3)
|
||
# ranges = pd.concat([high_low, high_close, low_close], axis=1)
|
||
# true_range = np.max(ranges, axis=1)
|
||
kdf['ATR'] = np.round(kdf['TR'].rolling(period).mean(), 3)
|
||
|
||
return kdf.drop(['HL','HC','LC'], axis = 1)
|
||
|
||
# A股数据 东方财富网
|
||
# all_data = ak.stock_zh_a_spot_em()
|
||
|
||
# 基金实时数据 东方财富网
|
||
# fund_etf_spot_em_df = ak.fund_etf_spot_em()
|
||
|
||
# 后复权历史数据
|
||
# fund_etf_hist_em_df = ak.fund_etf_hist_em(symbol="513300", period="daily", start_date="20130101", end_date="20240408", adjust="hfq")
|
||
# fund_etf_hist_em_df.to_csv('513300data.csv', index=False)
|
||
|
||
# data = pd.read_csv('513300data.csv')
|
||
|
||
|
||
# # 一、计算头寸规模
|
||
|
||
# # 真实波动幅度 = max (H-L, H-pdc, pdc-L)
|
||
|
||
# today = datetime.today()
|
||
# # print(today)
|
||
|
||
# # print(data.iloc[-1]['成交额'])
|
||
|
||
# TrueFlucs = []
|
||
# Nserious = np.zeros(101)
|
||
# last120days = np.arange(-120, -100)
|
||
# for i in last120days:
|
||
# H_L = data.iloc[i]['最高'] - data.iloc[i]['最低']
|
||
# H_PDC = data.iloc[i]['最高'] - data.iloc[i-1]['收盘']
|
||
# PDC_L = data.iloc[i-1]['收盘'] - data.iloc[i]['最低']
|
||
# TrueFlucs.append(np.max([H_L, H_PDC, PDC_L]))
|
||
|
||
# # 求简单平均,放入N序列第一个
|
||
# Nsimple = np.average(TrueFlucs)
|
||
# Nserious[0] = Nsimple
|
||
# # 计算-21到-1的N
|
||
# last100days = np.arange(-100, 0)
|
||
|
||
# for i in range(0,100):
|
||
# day = last100days[i]
|
||
# H_L = data.iloc[day]['最高'] - data.iloc[day]['最低']
|
||
# H_PDC = data.iloc[day]['最高'] - data.iloc[day-1]['收盘']
|
||
# PDC_L = data.iloc[day-1]['收盘'] - data.iloc[day]['最低']
|
||
# TrueFluc = np.max([H_L, H_PDC, PDC_L])
|
||
|
||
# Ntemp = (19 * Nserious[i] + TrueFluc)/20
|
||
# Nserious[i+1] = Ntemp
|
||
|
||
# # print(Nserious)
|
||
|
||
|
||
# total_rows = len(data)
|
||
# Ndata = np.zeros(total_rows)
|
||
# Ndata[total_rows-101:] = Nserious
|
||
# # NewColumn = [0]*(total_rows-101) + Nserious
|
||
# data['N'] = Ndata
|
||
|
||
# data.to_csv('513300data-N.csv', index=False)
|
||
# pass
|
||
|
||
|
||
# -----------------------更新atr----------------------
|
||
"""已有数据与新数据对比,补充新的N,同时更新数据库
|
||
"""
|
||
|
||
# Today = datetime.today()
|
||
# # print(Today)
|
||
# formatted_date = Today.strftime("%Y%m%d")
|
||
|
||
# # print(formatted_date)
|
||
# CurrentData = ak.fund_etf_hist_em(symbol="513300", period="daily", start_date="20130101", end_date=formatted_date, adjust="hfq")
|
||
|
||
# CurrentData = calc_sma_atr_pd(CurrentData, 20)
|
||
# CurrentData.to_csv('513300data-N.csv', index=False)
|
||
# pass
|
||
|
||
|
||
# ------------------计算头寸规模 资金10w, 1%波动------------
|
||
|
||
# money = 100000
|
||
# OldData = pd.read_csv('513300data-N.csv')
|
||
|
||
# N = OldData.iloc[-1]['ATR']
|
||
# # N = 0.473
|
||
# Price = OldData.iloc[-1]['收盘']
|
||
# # Price = 5.60
|
||
# EveryUnit = 0.0025 * money /(N*100*Price)
|
||
|
||
# print('单位',EveryUnit)
|
||
|
||
# print(113*100*Price)
|
||
|
||
|
||
class TurtleTrading(object):
|
||
"""对象范围较小,对某一个标的创建一个海龟,如513300,
|
||
计算ATR、
|
||
Position Size,
|
||
买入、卖出、加仓等行为
|
||
Args:
|
||
object (_type_): _description_
|
||
"""
|
||
def __init__(self, TradeCode) -> None:
|
||
self.TradeCode = TradeCode
|
||
|
||
def CalATR(self, ATRday, SaveOrNot):
|
||
"""计算某个标的的ATR,从上市日到今天, 计算后的数据保存在self.CurrentData
|
||
|
||
Args:
|
||
ATRday: 多少日ATR
|
||
SaveOrNot (_type_): 是否保存.csv数据
|
||
"""
|
||
Today = datetime.today()
|
||
# print(Today)
|
||
formatted_date = Today.strftime("%Y%m%d")
|
||
|
||
# print(formatted_date)
|
||
Code = f"{self.TradeCode}"
|
||
CurrentData = ak.fund_etf_hist_em(symbol=Code, period="daily", start_date="20130101", end_date=formatted_date, adjust="hfq")
|
||
|
||
self.CurrentData = calc_sma_atr_pd(CurrentData, ATRday)
|
||
if SaveOrNot:
|
||
self.CurrentData.to_csv('513300data-N.csv', index=False)
|
||
print("csv保存成功")
|
||
|
||
|
||
def CalPositionSize(self, RiskCoef, Capital):
|
||
"""计算PosizionSize 持有的单位,该单位某标的,1N波动对应RiskCoef * Capital资金
|
||
|
||
Args:
|
||
RiskCoef (_type_): 风险系数
|
||
Capital (_type_): 资金
|
||
"""
|
||
|
||
N = self.CurrentData.iloc[-1]['ATR']
|
||
# N = 0.473
|
||
Price = self.CurrentData.iloc[-1]['收盘']
|
||
# Price = 5.60
|
||
self.PositionSize = RiskCoef * Capital /( N*100*Price) # 默认用股票形式了 100
|
||
|
||
|
||
def ReadExistData(self, data):
|
||
"""除了通过发请求获取数据,也可以读本地的数据库,赋值给self.CurrentData
|
||
|
||
Args:
|
||
data (_type_): 本地csv名称
|
||
"""
|
||
self.CurrentData = pd.read_csv(data)
|
||
|
||
def DrawKLine(self, days):
|
||
"""画出k线图看看,画出最近days天的K线图
|
||
"""
|
||
|
||
# 日期部分
|
||
|
||
dates = pd.to_datetime(self.CurrentData['日期'][-days:])
|
||
# Klinedf['Data'] = pd.to_datetime(self.CurrentData['日期'])
|
||
Klinedf = pd.DataFrame()
|
||
# Klinedf.set_index = Klinedf['Data']
|
||
|
||
# 其他数据
|
||
Klinedf['Open'] = self.CurrentData['开盘'][-days:]
|
||
Klinedf['High'] = self.CurrentData['最高'][-days:]
|
||
Klinedf['Low'] = self.CurrentData['最低'][-days:]
|
||
Klinedf['Close'] = self.CurrentData['收盘'][-days:]
|
||
Klinedf['Volume'] = self.CurrentData['成交量'][-days:]
|
||
|
||
Klinedf.set_index(dates, inplace=True)
|
||
# 画图
|
||
mpf.plot(Klinedf, type='candle', style='yahoo', volume=False, mav=(5,), addplot=[mpf.make_addplot(self.Donchian[['Upper', 'Lower']])])
|
||
|
||
def calculate_donchian_channel(self, days, n):
|
||
"""
|
||
计算唐奇安通道days一共多少日, n多少日唐奇安
|
||
|
||
参数:
|
||
self.CurrentData (DataFrame): 包含价格数据的Pandas DataFrame,至少包含"High"和"Low"列
|
||
n (int): 时间周期
|
||
|
||
返回:self.Donchian
|
||
DataFrame: 唐奇安通道的DataFrame,包含"Upper", "Lower", 和 "Middle"列
|
||
"""
|
||
self.Donchian = pd.DataFrame()
|
||
# 计算最高价和最低价的N日移动平均线
|
||
self.Donchian['Upper'] = self.CurrentData['最高'][-days:].rolling(n).max()
|
||
self.Donchian['Lower'] = self.CurrentData['最低'][-days:].rolling(n).min()
|
||
|
||
# 计算中间线
|
||
self.Donchian['Middle'] = (self.Donchian['Upper'] + self.Donchian['Lower']) / 2
|
||
|
||
# return data[['Upper', 'Lower', 'Middle']]
|
||
|
||
nsdk513300 = TurtleTrading(513300)
|
||
# nsdk513300.CalATR(20, True)
|
||
nsdk513300.ReadExistData('513300data-N.csv')
|
||
# nsdk513300.CalPositionSize(0.0025, 100000)
|
||
nsdk513300.calculate_donchian_channel(500, 20)
|
||
nsdk513300.DrawKLine(500)
|
||
|
||
# print(nsdk513300.PositionSize) |