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)