From 082935662f44b8a3556c42f223445c49173adf63 Mon Sep 17 00:00:00 2001 From: guoyz Date: Thu, 29 May 2025 14:26:10 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EmailTest.py | 9 +-- TurtleOnTime.py | 97 +++++++++++++++----------- __pycache__/EmailTest.cpython-310.pyc | Bin 3864 -> 3869 bytes 3 files changed, 61 insertions(+), 45 deletions(-) diff --git a/EmailTest.py b/EmailTest.py index f0239f4..3e579c9 100755 --- a/EmailTest.py +++ b/EmailTest.py @@ -101,7 +101,8 @@ def parse_return_email(to_email, send_email_time): encoded_email = to_email.encode('utf-8') # 构建搜索条件:HEADER FROM "<发件人邮箱>, 时间大于 " - 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")}"' # 执行搜索操作 @@ -148,9 +149,9 @@ def parse_return_email(to_email, send_email_time): # 根据“实际买入价格-买入份额-手续费”格式解析body中的内容 parse_states = True body.split("-") - price = body.split("-")[0] - share = body.split("-")[1] - fee = body.split("-")[2] + price = float(body.split("-")[0]) + share = float(body.split("-")[1]) + fee = float(body.split("-")[2]) return parse_states, price, share, fee def check_email(to_email, send_email_time): diff --git a/TurtleOnTime.py b/TurtleOnTime.py index b199517..fa602ba 100644 --- a/TurtleOnTime.py +++ b/TurtleOnTime.py @@ -11,6 +11,7 @@ from dataclasses import dataclass import time import threading import yaml # 添加YAML支持 +import logging ''' todo @@ -90,10 +91,10 @@ class TurtleTrading(object): self.Capital = Capital self.cash = cash self.TrigerTime = 0 - self.BuyStates = list[BuyState] + self.BuyStates = [] - self.tradeslog = list[TradeLog] - self.BreakOutLog = list[BreakOutLog] + self.tradeslog = [] + self.BreakOutLog = [] self.PriceNow = 0.0 self.Donchian_20_up = 0.0 self.Donchian_10_down = 0.0 @@ -295,7 +296,7 @@ class TurtleTrading(object): def system1EnterSafe(self, PriceNow, TempDonchian55Upper): - if PriceNow > TempDonchian55Upper[-1]: # 保底的55日突破 + if PriceNow > TempDonchian55Upper: # 保底的55日突破 return True else: return False @@ -419,7 +420,7 @@ class TurtleTrading_OnTime(object): self.turtles = turtles # List of TurtleTrading instances self.user_email = user_email self.email_events = {} # Track email response events for each turtle - + logging.basicConfig(level=logging.INFO) # Load previous state from YAML if exists self.load_previous_state() @@ -451,8 +452,8 @@ class TurtleTrading_OnTime(object): body = f"{turtle.TradeCode},价格{price_now},份额{turtle.IntPositionSize} \n " body += "回复:实际买入价格-买入份额-手续费" 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分钟检测回信,解析邮件。 parsed_email_flag = False @@ -517,7 +518,7 @@ class TurtleTrading_OnTime(object): body = f"{turtle.TradeCode},价格{price_now},份额{turtle.IntPositionSize} \n " body += "回复:实际买入价格-买入份额-手续费" 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分钟检测回信,解析邮件。 @@ -617,7 +618,7 @@ class TurtleTrading_OnTime(object): body = f"{turtle.TradeCode},价格{price_now},份额{turtle.IntPositionSize * sale_shares} \n " body += "回复:实际卖出价格-卖出份额-手续费" 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分钟检测回信,解析邮件。 @@ -667,7 +668,7 @@ class TurtleTrading_OnTime(object): body = f"{turtle.TradeCode},价格{price_now},份额{turtle.IntPositionSize} \n " body += "回复:实际卖出价格-卖出份额-手续费" 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分钟检测回信,解析邮件。 @@ -795,7 +796,7 @@ class TurtleTrading_OnTime(object): # 准备数据 turtle.get_ready(100) 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_50_up = float(turtle.CurrentData['Donchian_50_upper'].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 == 15 and now.minute <= 0) ) - + is_trading_time = True if not is_trading_time: @@ -843,7 +844,7 @@ class TurtleTrading_OnTime(object): for turtle in self.turtles: mysql_database.delete_table(f"{turtle.TradeCode}") turtle.get_ready(100) - time.sleep(16.5*600) + time.sleep(16.5*600) def monitor_all_turtles(self): @@ -852,9 +853,19 @@ class TurtleTrading_OnTime(object): stock_data, etf_data = self.get_stocks_data() # 遍历所有turtle进行监控 + # 为每个 Turtle 启动一个线程 + threads = [] 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): @@ -862,15 +873,17 @@ class TurtleTrading_OnTime(object): now = datetime.now().time() 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": # 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 - + + # fake_price = 1.470 + # turtle.PriceNow = fake_price # 判断当前仓位状态并执行相应操作 if turtle.TrigerTime == 0: if turtle.system1EnterNormal( @@ -925,37 +938,39 @@ class TurtleTrading_OnTime(object): def start_email_thread(self, turtle:TurtleTrading, action, price_now): """启动邮件处理线程""" - event = threading.Event() - self.email_events[turtle.TradeCode] = event - - thread = threading.Thread( - target=self.handle_email_response, - args=(turtle, action, price_now, event) - ) - thread.start() + + self.handle_email_response(turtle, action, price_now) + - def handle_email_response(self, turtle:TurtleTrading, action, price_now, event): + def handle_email_response(self, turtle:TurtleTrading, action, price_now): """处理邮件响应的线程""" - # 发送邮件 - if action == "买入": - self.Buy_stock(turtle, price_now) - elif action == "加仓": - self.add_stock(turtle, price_now) - elif action == "止损": - self.stop_sale_stock(turtle, price_now) - elif action == "止盈": - self.out_sale_stock(turtle, price_now) - # 等待邮件响应 - event.wait() + try: + logging.info("handle_email_response is called with action: {}".format(action)) + # 发送邮件 + if action == "买入": + self.Buy_stock(turtle, price_now) + elif action == "加仓": + self.add_stock(turtle, price_now) + elif action == "止损": + self.stop_sale_stock(turtle, price_now) + elif action == "止盈": + self.out_sale_stock(turtle, price_now) + else: + logging.warning(f"Unknown action: {action} for TradeCode: {turtle.TradeCode}") + + + except Exception as e: + logging.error(f"Error in handle_email_response for TradeCode: {turtle.TradeCode}, Error: {e}") if __name__ == '__main__': 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) - a = TurtleTrading_OnTime(t, user_email) + a = TurtleTrading_OnTime([nsdk, cjdl], user_email) a.Start_short_system() # # 全是股票 diff --git a/__pycache__/EmailTest.cpython-310.pyc b/__pycache__/EmailTest.cpython-310.pyc index de27ca642fe50bd6f15e4c59569d0db31c0a0845..cd720e4ed9349eb0586914670c42b44947df32f6 100644 GIT binary patch delta 847 zcmYk)OH9;27zgl~(r&xmw#&Y|JdK=C9!3#F-G~uXzy)N{jYPoJ*Pu&%+T`w zCzHu|o4=BO;~xH0`Hp)&j|buy5Aa3xE6#IUYsWwNpqAYsI>Tkz4Q$&?@&YX2V^?J= z9d=X_V(L4zE7dVZHC2oasPc%IIbp3$MvhhuR`q8K7`Ylo+m^^!OgoyBNB0m3yV`RN zW*k;qcngW^h?Pk*iIgS(yyO`^8bu3*`;r@Ub*7VO8o42HjESS+n4ZN9aZ@IVyB0IO zu#f0Ro(Z<@Bz#=QZiF?Ht8rqJ^lR)XEbJwGwElr;Vg*Y)2HvRG zOlBTSmz#X9kgWn#ODDQ0PeU0}(tWg7RJ0H12hIYi|JYCs3f@35#NUT9W35zyfeBmyE&`W; z9^f)CENG~e)x!Ep<>9f09+BqJOBUy delta 783 zcmX}p&rj4q6bJB`rQLShPIs5xWm|qM%W6!F?qV?b6B43m+#vX4Q7}d{IuHd#7&fA0 zDhG@QqcL$VCb+S^a3EfY2V(paym-dMy9duEUi3W(w8>}Qw|&!2JB`Bo0(;DuMc~*> z7Vd9sFsaeM>Xr7Jmeo`JJ1u{%#)9Pj0+W&@7kZM?+?_K< zZV;Xd%;zS~*r^ujB7yhV(%?;L-mLzax#f&c0$W-<3!_tKp(`C&1mn5Dl`Kp~M0|oV z6_G)5Yk!cG$uJ#}AXRUMD#KeMxL& zZo+e2_!v6>a+XQ9)8TBluK6c!7kNlea(w5*sP^QsaUIyoIO`8i4tV7PyMn6 zRK+gY;t=FfaTrv#?pH(w?{_0dkfTU`4-c#3z*{U%sD|BtpjGG?7;+Lhjr1X9q#rr; z&S_Icr^mm5DTTz4DzK$5%sqUd9yzU}LwGHNWRZ)=Ffsyc(MfR$!)4?Oauul|X`~k! zMXn*&kumkdxu~UP|xY^B<$)um1o5