TurtleTrade/TurtleOnTime.py
2025-04-02 22:55:29 +08:00

247 lines
9.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import numpy as np
import math
import akshare as ak
import os
from datetime import datetime, timedelta, date
import pandas as pd
import mplfinance as mpf
import sqlite3
import stock_database
import mysql_database
def calc_sma_atr_pd(kdf,period):
"""计算TR与ATR
Args:
kdf (_type_): 历史数据
period (_type_): ATR周期
Returns:
_type_: 返回kdf增加TR与ATR列
"""
kdf['最高'] = kdf['最高'].astype(float)
kdf['最低'] = kdf['最低'].astype(float)
kdf['收盘'] = kdf['收盘'].astype(float)
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)
class TurtleTrading(object):
"""对象范围较小对某一个标的创建一个海龟如513300
计算ATR、唐奇安通道线
基础数据
Args:
object (_type_): _description_
"""
def __init__(self, TradeCode) -> None:
self.TradeCode = TradeCode
def GetRecentData(self):
"""获取某个标的的最近数据,从两年前到今天, 计算后的数据保存在self.CurrentData
Returns:
_type_: _description_
"""
Today = datetime.today()
# print(Today)
formatted_date = Today.strftime("%Y%m%d")
two_years_ago = (date.today() - timedelta(days=365*2)).strftime("%Y%m%d")
# print(formatted_date)
Code = f"{self.TradeCode}"
CurrentData = ak.fund_etf_hist_em(symbol=Code, period="daily", start_date=two_years_ago, end_date=formatted_date, adjust="")
# 将日期列转换为datetime
CurrentData = pd.DataFrame(CurrentData)
CurrentData['日期'] = pd.to_datetime(CurrentData['日期'])
# print(type(CurrentData['日期'].iloc[0]))
CurrentData.set_index('日期', inplace=True)
# CurrentData.reset_index(inplace=True)
# print(type(CurrentData['日期'].iloc[0]))
# create table
# stock_database.create_table(Code)
# stock_database.insert_data(Code, CurrentData)
# mysql_database.insert_db(CurrentData, Code, True, "'日期'")
self.CurrentData = CurrentData
# return self.CurrentData
def CalATR(self, data, ATRday):
"""计算某个标的的ATR从上市日到今天, 计算后的数据保存在self.CurrentData
Args:
ATRday: 多少日ATR
SaveOrNot (_type_): 是否保存.csv数据
"""
self.CurrentData = calc_sma_atr_pd(data, ATRday)
self.N = self.CurrentData['ATR']
# return self.N
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['Date'] = self.CurrentData['日期'][-days:]
Klinedf['Open'] = self.CurrentData['开盘'][-days:].astype(float)
Klinedf['High'] = self.CurrentData['最高'][-days:].astype(float)
Klinedf['Low'] = self.CurrentData['最低'][-days:].astype(float)
Klinedf['Close'] = self.CurrentData['收盘'][-days:].astype(float)
Klinedf['Volume'] = self.CurrentData['成交量'][-days:].astype(float)
Klinedf.set_index(pd.to_datetime(Klinedf['Date']), inplace=True)
# 画图
mpf.plot(Klinedf, type='candle', style='yahoo', volume=False, mav=(5,), addplot=[mpf.make_addplot(self.Donchian_up['Upper'][-days:]), mpf.make_addplot(self.Donchian_down['lower'][-days:])], title=f"{self.TradeCode} K线图")
def calculate_donchian_channel_up(self, n):
"""
计算n日唐奇安上通道
参数:
self.CurrentData (DataFrame): 包含价格数据的Pandas DataFrame包含"High"
n (int): 时间周期
返回:self.Donchian
DataFrame: 唐奇安通道的DataFrame包含"Upper"
"""
Donchian = pd.DataFrame() # 创建一个空的DataFrame用于存储唐奇安通道数据
# 计算最高价和最低价的N日移动平均线
Donchian['Upper'] = self.CurrentData['最高'].rolling(n).max() # 使用rolling函数计算n日最高价的移动最大值
# # 计算中间线
# Donchian['Middle'] = (self.Donchian['Upper'] + self.Donchian['Lower']) / 2 # 计算上通道和下通道的中间线,但此行代码被注释掉了
return Donchian # 返回包含唐奇安上通道的DataFrame
def calculate_donchian_channel_down(self, n):
"""
计算n日唐奇安上通道
参数:
self.CurrentData (DataFrame): 包含价格数据的Pandas DataFrame包含"High"
n (int): 时间周期
返回:self.Donchian
DataFrame: 唐奇安通道的DataFrame包含"Upper"
"""
Donchian = pd.DataFrame()
# 计算最高价和最低价的N日移动平均线
Donchian['lower'] = self.CurrentData['最低'].rolling(n).min()
# # 计算中间线
# Donchian['Middle'] = (self.Donchian['Upper'] + self.Donchian['Lower']) / 2
return Donchian
def get_ready(self, days):
"""创建一个turtle对象获取数据计算ATR计算唐奇安通道
Args:
days (_type_): _description_
n (_type_): _description_
"""
# 检查mysql数据库中是否存在该股票的数据 或者数据库最后一条的时间距离今天是否两天以上
current_date = date.today()
threshold_date = current_date - timedelta(days=2)
last_update = mysql_database.check_db_table_last_date(f"{self.TradeCode}")
if not mysql_database.check_db_table(f"{self.TradeCode}") or last_update < threshold_date:
# 如果不存在则从akshare获取数据并保存到mysql数据库
if mysql_database.check_db_table(f"{self.TradeCode}") and last_update < threshold_date:
mysql_database.delete_table(f"{self.TradeCode}")
self.GetRecentData()
else:
# 如果存在则从mysql数据库中读取数据
self.CurrentData = mysql_database.fetch_all_data(f"{self.TradeCode}")
# 计算ATR
self.CalATR(self.CurrentData, 20)
# 计算唐奇安通道
self.Donchian_up = self.calculate_donchian_channel_up(20)
self.Donchian_down = self.calculate_donchian_channel_down(10)
# 画图
# self.DrawKLine(days)
# 把self.N, self.Donchian_up, self.Donchian_down, 添加到self.CurrentData后面保存到mysql数据库
self.CurrentData = pd.concat([self.CurrentData, self.Donchian_up, self.Donchian_down], axis=1)
Code = f"{self.TradeCode}"
mysql_database.insert_db(self.CurrentData, Code, True, "日期")
# 一天结束计算ATR计算唐奇安通道追加到已有的mysql数据库中
def day_end(self):
pass
class TurtleTrading_OnTime(object):
''' 实时监测主程序可以处理多个turtle
1、获取实时大盘数据
2、根据turtles的代码比较是否触发条件
3、实时监测主流程
'''
def __init__(self):
pass
def get_stocks_data(self):
"""获取实时股票、基金数据,不保存
"""
stock_zh_a_spot_df = ak.stock_zh_a_spot_em()
stock_zh_a_spot_df = stock_zh_a_spot_df.dropna(subset=['最新价'])
# # print(stock_zh_a_spot_df)
# # stock_zh_a_spot_df第一列加上时间精确到分钟
# stock_zh_a_spot_df['时间'] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# mysql_database.insert_db(stock_zh_a_spot_df, "stock_price", True, "代码")
# etf_data = ak.fund_etf_spot_em()
etf_data = ak.fund_etf_spot_ths()
etf_data = etf_data.dropna(subset=['当前-单位净值'])
# etf_data['时间'] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# mysql_database.insert_db(etf_data, "etf_price", True, "代码")
if __name__ == '__main__':
# t = TurtleTrading('513300')
# t.get_ready(100)
a = TurtleTrading_OnTime()
a.get_stocks_data()
# # 全是股票
# stock_zh_a_spot_df = ak.stock_zh_a_spot_em()
# # stock_zh_a_spot_df.to_csv("stock_zh_a_spot.txt", sep="\t", index=False, encoding="utf-8")
# stock_zh_a_spot_df = stock_zh_a_spot_df.dropna(subset=['最新价'])
# print(stock_zh_a_spot_df)
# # 全是基金
# etf_data = ak.fund_etf_spot_em()
# etf_data = etf_data.dropna(subset=['最新价'])
# etf_data.to_csv("fund_etf_spot.txt", sep="\t", index=False, encoding="utf-8")
# print(etf_data)