This commit is contained in:
guoyz 2025-05-29 14:26:10 +08:00
parent 9bca280232
commit 082935662f
3 changed files with 61 additions and 45 deletions

View File

@ -101,7 +101,8 @@ def parse_return_email(to_email, send_email_time):
encoded_email = to_email.encode('utf-8') encoded_email = to_email.encode('utf-8')
# 构建搜索条件HEADER FROM "<发件人邮箱>, 时间大于 <send_email_time>" # 构建搜索条件HEADER FROM "<发件人邮箱>, 时间大于 <send_email_time>"
search_criteria = f'FROM "{encoded_email.decode("utf-8")}" SINCE "{send_email_time}"' search_criteria = ['FROM', encoded_email.decode('utf-8'), 'SINCE', send_email_time]
# search_criteria = f'FROM "{encoded_email.decode("utf-8")}"' # search_criteria = f'FROM "{encoded_email.decode("utf-8")}"'
# 执行搜索操作 # 执行搜索操作
@ -148,9 +149,9 @@ def parse_return_email(to_email, send_email_time):
# 根据“实际买入价格-买入份额-手续费”格式解析body中的内容 # 根据“实际买入价格-买入份额-手续费”格式解析body中的内容
parse_states = True parse_states = True
body.split("-") body.split("-")
price = body.split("-")[0] price = float(body.split("-")[0])
share = body.split("-")[1] share = float(body.split("-")[1])
fee = body.split("-")[2] fee = float(body.split("-")[2])
return parse_states, price, share, fee return parse_states, price, share, fee
def check_email(to_email, send_email_time): def check_email(to_email, send_email_time):

View File

@ -11,6 +11,7 @@ from dataclasses import dataclass
import time import time
import threading import threading
import yaml # 添加YAML支持 import yaml # 添加YAML支持
import logging
''' '''
todo todo
@ -90,10 +91,10 @@ class TurtleTrading(object):
self.Capital = Capital self.Capital = Capital
self.cash = cash self.cash = cash
self.TrigerTime = 0 self.TrigerTime = 0
self.BuyStates = list[BuyState] self.BuyStates = []
self.tradeslog = list[TradeLog] self.tradeslog = []
self.BreakOutLog = list[BreakOutLog] self.BreakOutLog = []
self.PriceNow = 0.0 self.PriceNow = 0.0
self.Donchian_20_up = 0.0 self.Donchian_20_up = 0.0
self.Donchian_10_down = 0.0 self.Donchian_10_down = 0.0
@ -295,7 +296,7 @@ class TurtleTrading(object):
def system1EnterSafe(self, PriceNow, TempDonchian55Upper): def system1EnterSafe(self, PriceNow, TempDonchian55Upper):
if PriceNow > TempDonchian55Upper[-1]: # 保底的55日突破 if PriceNow > TempDonchian55Upper: # 保底的55日突破
return True return True
else: else:
return False return False
@ -419,7 +420,7 @@ class TurtleTrading_OnTime(object):
self.turtles = turtles # List of TurtleTrading instances self.turtles = turtles # List of TurtleTrading instances
self.user_email = user_email self.user_email = user_email
self.email_events = {} # Track email response events for each turtle self.email_events = {} # Track email response events for each turtle
logging.basicConfig(level=logging.INFO)
# Load previous state from YAML if exists # Load previous state from YAML if exists
self.load_previous_state() self.load_previous_state()
@ -451,8 +452,8 @@ class TurtleTrading_OnTime(object):
body = f"{turtle.TradeCode},价格{price_now},份额{turtle.IntPositionSize} \n " body = f"{turtle.TradeCode},价格{price_now},份额{turtle.IntPositionSize} \n "
body += "回复:实际买入价格-买入份额-手续费" body += "回复:实际买入价格-买入份额-手续费"
send_email(subject, body, self.user_email) send_email(subject, body, self.user_email)
send_email_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") # send_email_time = datetime.strftime(datetime.now(),"%Y%m%d %H:%M:%S").date()
send_email_time = datetime.now().date()
#每隔1分钟检测回信解析邮件。 #每隔1分钟检测回信解析邮件。
parsed_email_flag = False parsed_email_flag = False
@ -517,7 +518,7 @@ class TurtleTrading_OnTime(object):
body = f"{turtle.TradeCode},价格{price_now},份额{turtle.IntPositionSize} \n " body = f"{turtle.TradeCode},价格{price_now},份额{turtle.IntPositionSize} \n "
body += "回复:实际买入价格-买入份额-手续费" body += "回复:实际买入价格-买入份额-手续费"
send_email(subject, body, self.user_email) send_email(subject, body, self.user_email)
send_email_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") send_email_time = datetime.now().date()
#每隔1分钟检测回信解析邮件。 #每隔1分钟检测回信解析邮件。
@ -617,7 +618,7 @@ class TurtleTrading_OnTime(object):
body = f"{turtle.TradeCode},价格{price_now},份额{turtle.IntPositionSize * sale_shares} \n " body = f"{turtle.TradeCode},价格{price_now},份额{turtle.IntPositionSize * sale_shares} \n "
body += "回复:实际卖出价格-卖出份额-手续费" body += "回复:实际卖出价格-卖出份额-手续费"
send_email(subject, body, self.user_email) send_email(subject, body, self.user_email)
send_email_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") send_email_time = datetime.now().date()
# 每隔1分钟检测回信解析邮件。 # 每隔1分钟检测回信解析邮件。
@ -667,7 +668,7 @@ class TurtleTrading_OnTime(object):
body = f"{turtle.TradeCode},价格{price_now},份额{turtle.IntPositionSize} \n " body = f"{turtle.TradeCode},价格{price_now},份额{turtle.IntPositionSize} \n "
body += "回复:实际卖出价格-卖出份额-手续费" body += "回复:实际卖出价格-卖出份额-手续费"
send_email(subject, body, self.user_email) send_email(subject, body, self.user_email)
send_email_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") send_email_time = datetime.now().date()
# 每隔1分钟检测回信解析邮件。 # 每隔1分钟检测回信解析邮件。
@ -795,7 +796,7 @@ class TurtleTrading_OnTime(object):
# 准备数据 # 准备数据
turtle.get_ready(100) turtle.get_ready(100)
turtle.N = float(turtle.CurrentData['ATR'].iloc[-1]) turtle.N = float(turtle.CurrentData['ATR'].iloc[-1])
turtle.prev_heigh = float(turtle.CurrentData['最高'].iloc[-1]) turtle.prev_heigh = float(turtle.CurrentData['最高'].iloc[-1])
turtle.Donchian_20_up = float(turtle.CurrentData['Donchian_20_upper'].iloc[-1]) turtle.Donchian_20_up = float(turtle.CurrentData['Donchian_20_upper'].iloc[-1])
turtle.Donchian_50_up = float(turtle.CurrentData['Donchian_50_upper'].iloc[-1]) turtle.Donchian_50_up = float(turtle.CurrentData['Donchian_50_upper'].iloc[-1])
turtle.Donchian_10_down = float(turtle.CurrentData['Donchian_10_lower'].iloc[-1]) turtle.Donchian_10_down = float(turtle.CurrentData['Donchian_10_lower'].iloc[-1])
@ -821,7 +822,7 @@ class TurtleTrading_OnTime(object):
(now.hour == 14 and 0 <= now.minute <= 59) or (now.hour == 14 and 0 <= now.minute <= 59) or
(now.hour == 15 and now.minute <= 0) (now.hour == 15 and now.minute <= 0)
) )
is_trading_time = True
if not is_trading_time: if not is_trading_time:
@ -852,9 +853,19 @@ class TurtleTrading_OnTime(object):
stock_data, etf_data = self.get_stocks_data() stock_data, etf_data = self.get_stocks_data()
# 遍历所有turtle进行监控 # 遍历所有turtle进行监控
# 为每个 Turtle 启动一个线程
threads = []
for turtle in self.turtles: for turtle in self.turtles:
self.monitor_single_turtle(turtle, stock_data, etf_data) thread = threading.Thread(
target=self.monitor_single_turtle,
args=(turtle, stock_data, etf_data)
)
thread.start()
threads.append(thread)
# 可选:等待所有线程完成(如果需要)
for thread in threads:
thread.join()
def monitor_single_turtle(self, turtle: TurtleTrading, stock_data, etf_data): def monitor_single_turtle(self, turtle: TurtleTrading, stock_data, etf_data):
@ -862,15 +873,17 @@ class TurtleTrading_OnTime(object):
now = datetime.now().time() now = datetime.now().time()
if turtle.type == "stock": if turtle.type == "stock":
turtle.PriceNow = float(stock_data.loc[etf_data['代码'] == self.turtle.TradeCode, '最新价'].values[0]) turtle.PriceNow = float(stock_data.loc[stock_data['代码'] == turtle.TradeCode, '最新价'].values[0])
elif turtle.type == "etf": elif turtle.type == "etf":
# self.turtle.PriceNow = float(etf_data.loc[etf_data['基金代码'] == self.turtle.TradeCode, '当前-单位净值'].values[0]) # self.turtle.PriceNow = float(etf_data.loc[etf_data['基金代码'] == self.turtle.TradeCode, '当前-单位净值'].values[0])
turtle.PriceNow = float(etf_data.loc[etf_data['代码'] == self.turtle.TradeCode, '最新价'].values[0]) turtle.PriceNow = float(etf_data.loc[etf_data['代码'] == turtle.TradeCode, '最新价'].values[0])
if now.hour == 9 and now.minute == 30 and self.turtle.PriceNow > self.turtle.prev_heigh: if now.hour == 9 and now.minute == 30 and turtle.PriceNow > turtle.prev_heigh:
turtle.is_gap_up = True turtle.is_gap_up = True
# fake_price = 1.470
# turtle.PriceNow = fake_price
# 判断当前仓位状态并执行相应操作 # 判断当前仓位状态并执行相应操作
if turtle.TrigerTime == 0: if turtle.TrigerTime == 0:
if turtle.system1EnterNormal( if turtle.system1EnterNormal(
@ -925,17 +938,15 @@ class TurtleTrading_OnTime(object):
def start_email_thread(self, turtle:TurtleTrading, action, price_now): def start_email_thread(self, turtle:TurtleTrading, action, price_now):
"""启动邮件处理线程""" """启动邮件处理线程"""
event = threading.Event()
self.email_events[turtle.TradeCode] = event
thread = threading.Thread( self.handle_email_response(turtle, action, price_now)
target=self.handle_email_response,
args=(turtle, action, price_now, event)
)
thread.start()
def handle_email_response(self, turtle:TurtleTrading, action, price_now, event):
def handle_email_response(self, turtle:TurtleTrading, action, price_now):
"""处理邮件响应的线程""" """处理邮件响应的线程"""
try:
logging.info("handle_email_response is called with action: {}".format(action))
# 发送邮件 # 发送邮件
if action == "买入": if action == "买入":
self.Buy_stock(turtle, price_now) self.Buy_stock(turtle, price_now)
@ -945,17 +956,21 @@ class TurtleTrading_OnTime(object):
self.stop_sale_stock(turtle, price_now) self.stop_sale_stock(turtle, price_now)
elif action == "止盈": elif action == "止盈":
self.out_sale_stock(turtle, price_now) self.out_sale_stock(turtle, price_now)
else:
logging.warning(f"Unknown action: {action} for TradeCode: {turtle.TradeCode}")
# 等待邮件响应
event.wait() except Exception as e:
logging.error(f"Error in handle_email_response for TradeCode: {turtle.TradeCode}, Error: {e}")
if __name__ == '__main__': if __name__ == '__main__':
user_email = "guoyize2209@163.com" user_email = "guoyize2209@163.com"
t = TurtleTrading('513870', "etf", 0.0025, 100000, 200000) nsdk = TurtleTrading('513870', "etf", 0.0025, 100000, 200000)
cjdl = TurtleTrading('600900', "stock", 0.0025, 100000, 200000)
# t.get_ready(100) # t.get_ready(100)
a = TurtleTrading_OnTime(t, user_email) a = TurtleTrading_OnTime([nsdk, cjdl], user_email)
a.Start_short_system() a.Start_short_system()
# # 全是股票 # # 全是股票