states更新
This commit is contained in:
parent
d0b92aa1ef
commit
9bca280232
@ -10,6 +10,7 @@ from EmailTest import send_email, parse_return_email
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
import time
|
import time
|
||||||
import threading
|
import threading
|
||||||
|
import yaml # 添加YAML支持
|
||||||
|
|
||||||
'''
|
'''
|
||||||
todo
|
todo
|
||||||
@ -335,7 +336,41 @@ class TurtleTrading(object):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def day_end(self):
|
def day_end(self):
|
||||||
pass
|
"""Save current state to YAML file at the end of the day"""
|
||||||
|
# Create state directory if not exists
|
||||||
|
state_dir = "state"
|
||||||
|
if not os.path.exists(state_dir):
|
||||||
|
os.makedirs(state_dir)
|
||||||
|
|
||||||
|
# Generate filename with current date
|
||||||
|
today = datetime.now().strftime("%Y-%m-%d")
|
||||||
|
filename = os.path.join(state_dir, f"{today}.yaml")
|
||||||
|
|
||||||
|
# Save state to YAML
|
||||||
|
state_data = {
|
||||||
|
"turtles": [
|
||||||
|
{
|
||||||
|
"TradeCode": t.TradeCode,
|
||||||
|
"type": t.type,
|
||||||
|
"riskcoe": t.riskcoe,
|
||||||
|
"Capital": t.Capital,
|
||||||
|
"cash": t.cash,
|
||||||
|
"TrigerTime": t.TrigerTime,
|
||||||
|
"BuyStates": [vars(bs) for bs in t.BuyStates],
|
||||||
|
"tradeslog": [vars(tl) for tl in t.tradeslog],
|
||||||
|
"BreakOutLog": [vars(bol) for bol in t.BreakOutLog],
|
||||||
|
"PriceNow": t.PriceNow,
|
||||||
|
"Donchian_20_up": t.Donchian_20_up,
|
||||||
|
"Donchian_10_down": t.Donchian_10_down,
|
||||||
|
"Donchian_50_up": t.Donchian_50_up,
|
||||||
|
"is_gap_up": t.is_gap_up,
|
||||||
|
"prev_heigh": t.prev_heigh
|
||||||
|
} for t in self.turtles
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
with open(filename, 'w') as f:
|
||||||
|
yaml.dump(state_data, f)
|
||||||
|
|
||||||
class TurtleTrading_OnTime(object):
|
class TurtleTrading_OnTime(object):
|
||||||
''' 实时监测主程序,可以处理多个turtle
|
''' 实时监测主程序,可以处理多个turtle
|
||||||
@ -345,11 +380,51 @@ class TurtleTrading_OnTime(object):
|
|||||||
3、实时监测主流程
|
3、实时监测主流程
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
def load_previous_state(self):
|
||||||
|
"""Load previous state from YAML file if exists"""
|
||||||
|
state_dir = "state"
|
||||||
|
today = datetime.now().strftime("%Y-%m-%d")
|
||||||
|
yesterday = (datetime.now() - timedelta(days=1)).strftime("%Y-%m-%d")
|
||||||
|
filename = os.path.join(state_dir, f"{yesterday}.yaml")
|
||||||
|
|
||||||
|
if os.path.exists(filename):
|
||||||
|
with open(filename, 'r') as f:
|
||||||
|
state_data = yaml.safe_load(f)
|
||||||
|
|
||||||
|
# Restore state
|
||||||
|
for turtle_data in state_data.get('turtles', []):
|
||||||
|
# Find or create TurtleTrading instance
|
||||||
|
turtle = next((t for t in self.turtles if t.TradeCode == turtle_data['TradeCode']), None)
|
||||||
|
if not turtle:
|
||||||
|
# Create new instance if not found (should not happen)
|
||||||
|
turtle = TurtleTrading(**turtle_data)
|
||||||
|
self.turtles.append(turtle)
|
||||||
|
|
||||||
|
# Restore attributes
|
||||||
|
turtle.TradeCode = turtle_data['TradeCode']
|
||||||
|
turtle.type = turtle_data['type']
|
||||||
|
turtle.riskcoe = turtle_data['riskcoe']
|
||||||
|
turtle.Capital = turtle_data['Capital']
|
||||||
|
turtle.cash = turtle_data['cash']
|
||||||
|
turtle.TrigerTime = turtle_data['TrigerTime']
|
||||||
|
turtle.BuyStates = [BuyState(**bs) for bs in turtle_data['BuyStates']]
|
||||||
|
turtle.tradeslog = [TradeLog(**tl) for tl in turtle_data['tradeslog']]
|
||||||
|
turtle.BreakOutLog = [BreakOutLog(**bol) for bol in turtle_data['BreakOutLog']]
|
||||||
|
turtle.PriceNow = turtle_data['PriceNow']
|
||||||
|
turtle.Donchian_20_up = turtle_data['Donchian_20_up']
|
||||||
|
turtle.Donchian_10_down = turtle_data['Donchian_10_down']
|
||||||
|
turtle.Donchian_50_up = turtle_data['Donchian_50_up']
|
||||||
|
turtle.is_gap_up = turtle_data['is_gap_up']
|
||||||
|
turtle.prev_heigh = turtle_data['prev_heigh']
|
||||||
|
|
||||||
def __init__(self, turtles: list[TurtleTrading], user_email):
|
def __init__(self, turtles: list[TurtleTrading], user_email):
|
||||||
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
|
||||||
|
|
||||||
|
# Load previous state from YAML if exists
|
||||||
|
self.load_previous_state()
|
||||||
|
|
||||||
def get_stocks_data(self):
|
def get_stocks_data(self):
|
||||||
"""获取实时股票、基金数据,不保存
|
"""获取实时股票、基金数据,不保存
|
||||||
"""
|
"""
|
||||||
@ -369,13 +444,13 @@ class TurtleTrading_OnTime(object):
|
|||||||
# mysql_database.insert_db(etf_data, "etf_price", True, "代码")
|
# mysql_database.insert_db(etf_data, "etf_price", True, "代码")
|
||||||
return stock_data, etf_data
|
return stock_data, etf_data
|
||||||
|
|
||||||
def Buy_stock(self, price_now):
|
def Buy_stock(self, turtle: TurtleTrading, price_now):
|
||||||
# 发送邮件 代码self.turtle.TradeCode, 建议买入价格price_now,买入份额self.turtle.IntPositionSize
|
# 发送邮件 代码self.turtle.TradeCode, 建议买入价格price_now,买入份额self.turtle.IntPositionSize
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
subject = "买入"
|
subject = "买入"
|
||||||
body = f"{self.turtle.TradeCode},价格{price_now},份额{self.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().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
@ -394,23 +469,23 @@ class TurtleTrading_OnTime(object):
|
|||||||
break
|
break
|
||||||
|
|
||||||
# 成功买入
|
# 成功买入
|
||||||
self.turtle.TrigerTime += 1
|
turtle.TrigerTime += 1
|
||||||
# 记录self.turtle.BuyStates
|
# 记录self.turtle.BuyStates
|
||||||
add_price = buy_price + 1/2 * self.turtle.N
|
add_price = buy_price + 1/2 * turtle.N
|
||||||
stop_price = buy_price - 2 * self.turtle.N
|
stop_price = buy_price - 2 * turtle.N
|
||||||
cost = buy_price * buy_share - fee
|
cost = buy_price * buy_share - fee
|
||||||
available_cash = self.turtle.Capital - cost
|
available_cash = turtle.Capital - cost
|
||||||
|
|
||||||
buy_this_time = BuyState(self.turtle.TrigerTime,
|
buy_this_time = BuyState(turtle.TrigerTime,
|
||||||
buy_price,
|
buy_price,
|
||||||
add_price,
|
add_price,
|
||||||
stop_price,
|
stop_price,
|
||||||
False,
|
False,
|
||||||
buy_share,
|
buy_share,
|
||||||
self.turtle.N,
|
turtle.N,
|
||||||
available_cash)
|
available_cash)
|
||||||
|
|
||||||
self.turtle.BuyStates.append(buy_this_time)
|
turtle.BuyStates.append(buy_this_time)
|
||||||
|
|
||||||
# 记录self.turtle.tradeslog
|
# 记录self.turtle.tradeslog
|
||||||
today = datetime.now().strftime("%Y-%m-%d")
|
today = datetime.now().strftime("%Y-%m-%d")
|
||||||
@ -419,19 +494,19 @@ class TurtleTrading_OnTime(object):
|
|||||||
buy_price,
|
buy_price,
|
||||||
buy_share,
|
buy_share,
|
||||||
cost,
|
cost,
|
||||||
self.turtle.N,
|
turtle.N,
|
||||||
available_cash,
|
available_cash,
|
||||||
all_shares=buy_share,
|
all_shares=buy_share,
|
||||||
all_cost=cost,
|
all_cost=cost,
|
||||||
Net_value=buy_price * buy_share,
|
Net_value=buy_price * buy_share,
|
||||||
Net_return=0)
|
Net_return=0)
|
||||||
self.turtle.tradeslog.append(log_this_time)
|
turtle.tradeslog.append(log_this_time)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def add_stock(self, price_now):
|
def add_stock(self, turtle: TurtleTrading, price_now):
|
||||||
"""加仓
|
"""加仓
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -441,7 +516,7 @@ class TurtleTrading_OnTime(object):
|
|||||||
# 加仓
|
# 加仓
|
||||||
|
|
||||||
subject = "加仓"
|
subject = "加仓"
|
||||||
body = f"{self.turtle.TradeCode},价格{price_now},份额{self.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().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
@ -460,26 +535,26 @@ class TurtleTrading_OnTime(object):
|
|||||||
break
|
break
|
||||||
|
|
||||||
# 成功买入
|
# 成功买入
|
||||||
self.turtle.TrigerTime += 1
|
turtle.TrigerTime += 1
|
||||||
# 记录self.turtle.BuyStates
|
# 记录self.turtle.BuyStates
|
||||||
add_price = buy_price + 1/2 * self.turtle.N
|
add_price = buy_price + 1/2 * turtle.N
|
||||||
stop_price = buy_price - 2 * self.turtle.N
|
stop_price = buy_price - 2 * turtle.N
|
||||||
cost = buy_price * buy_share - fee
|
cost = buy_price * buy_share - fee
|
||||||
available_cash = self.turtle.BuyStates[-1].available_cash - cost
|
available_cash = turtle.BuyStates[-1].available_cash - cost
|
||||||
all_shares = buy_share + self.turtle.BuyStates[-1].all_shares
|
all_shares = buy_share + turtle.BuyStates[-1].all_shares
|
||||||
all_cost = cost + self.turtle.BuyStates[-1].all_cost
|
all_cost = cost + turtle.BuyStates[-1].all_cost
|
||||||
net_value = buy_price * all_shares
|
net_value = buy_price * all_shares
|
||||||
net_return = net_value - all_cost
|
net_return = net_value - all_cost
|
||||||
buy_this_time = BuyState(self.turtle.TrigerTime,
|
buy_this_time = BuyState(turtle.TrigerTime,
|
||||||
buy_price,
|
buy_price,
|
||||||
add_price,
|
add_price,
|
||||||
stop_price,
|
stop_price,
|
||||||
self.turtle.is_gap_up,
|
turtle.is_gap_up,
|
||||||
buy_share,
|
buy_share,
|
||||||
self.turtle.N,
|
turtle.N,
|
||||||
available_cash)
|
available_cash)
|
||||||
|
|
||||||
self.turtle.BuyStates.append(buy_this_time)
|
turtle.BuyStates.append(buy_this_time)
|
||||||
|
|
||||||
|
|
||||||
today = datetime.now().strftime("%Y-%m-%d")
|
today = datetime.now().strftime("%Y-%m-%d")
|
||||||
@ -488,43 +563,43 @@ class TurtleTrading_OnTime(object):
|
|||||||
buy_price,
|
buy_price,
|
||||||
buy_share,
|
buy_share,
|
||||||
cost,
|
cost,
|
||||||
self.turtle.N,
|
turtle.N,
|
||||||
available_cash,
|
available_cash,
|
||||||
all_shares,
|
all_shares,
|
||||||
all_cost,
|
all_cost,
|
||||||
net_value,
|
net_value,
|
||||||
net_return)
|
net_return)
|
||||||
self.turtle.tradeslog.append(log_this_time)
|
turtle.tradeslog.append(log_this_time)
|
||||||
|
|
||||||
# 处理其他次买入的止损价格
|
# 处理其他次买入的止损价格
|
||||||
# 检查BuyStates中有几个gap_up,返回个数和索引
|
# 检查BuyStates中有几个gap_up,返回个数和索引
|
||||||
gap_up_num = 0
|
gap_up_num = 0
|
||||||
gap_up_index = []
|
gap_up_index = []
|
||||||
for i in range(len(self.turtle.BuyStates)):
|
for i in range(len(turtle.BuyStates)):
|
||||||
if self.turtle.BuyStates[i].is_gap_up:
|
if turtle.BuyStates[i].is_gap_up:
|
||||||
gap_up_num += 1
|
gap_up_num += 1
|
||||||
gap_up_index.append(i)
|
gap_up_index.append(i)
|
||||||
if gap_up_num == 0:
|
if gap_up_num == 0:
|
||||||
# 之前BuyStates中的stop_price = stop_price
|
# 之前BuyStates中的stop_price = stop_price
|
||||||
for j in range(len(self.turtle.BuyStates)):
|
for j in range(len(turtle.BuyStates)):
|
||||||
self.turtle.BuyStates[j].stop_price = stop_price
|
turtle.BuyStates[j].stop_price = stop_price
|
||||||
|
|
||||||
if not self.turtle.is_gap_up and gap_up_num == 1:
|
if not turtle.is_gap_up and gap_up_num == 1:
|
||||||
if gap_up_index[0] == 1:
|
if gap_up_index[0] == 1:
|
||||||
number_tobe_change = self.turtle.TrigerTime -1 - gap_up_index[0]
|
number_tobe_change = turtle.TrigerTime -1 - gap_up_index[0]
|
||||||
for k in range(number_tobe_change):
|
for k in range(number_tobe_change):
|
||||||
self.turtle.BuyStates[k+1].stop_price = stop_price
|
turtle.BuyStates[k+1].stop_price = stop_price
|
||||||
|
|
||||||
elif gap_up_index[0] == 2:
|
elif gap_up_index[0] == 2:
|
||||||
self.turtle.BuyStates[2].stop_price = stop_price
|
turtle.BuyStates[2].stop_price = stop_price
|
||||||
|
|
||||||
elif not self.turtle.is_gap_up and gap_up_num == 2:
|
elif not turtle.is_gap_up and gap_up_num == 2:
|
||||||
number_tobe_change = 2
|
number_tobe_change = 2
|
||||||
for k in range(number_tobe_change):
|
for k in range(number_tobe_change):
|
||||||
self.turtle.BuyStates[k+1].stop_price = stop_price
|
turtle.BuyStates[k+1].stop_price = stop_price
|
||||||
|
|
||||||
|
|
||||||
def stop_sale_stock(self, price_now):
|
def stop_sale_stock(self, turtle: TurtleTrading, price_now):
|
||||||
"""止损卖出
|
"""止损卖出
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -533,15 +608,15 @@ class TurtleTrading_OnTime(object):
|
|||||||
|
|
||||||
# 判断需要卖出几份
|
# 判断需要卖出几份
|
||||||
sale_shares = 0
|
sale_shares = 0
|
||||||
for i in range(len(self.turtle.BuyStates)):
|
for i in range(len(turtle.BuyStates)):
|
||||||
if price_now <= self.turtle.BuyStates[i].stop_price:
|
if price_now <= turtle.BuyStates[i].stop_price:
|
||||||
sale_shares += 1
|
sale_shares += 1
|
||||||
break
|
break
|
||||||
# 比较price_now与self.turtle.BuyStates[-1].stop_price
|
# 比较price_now与self.turtle.BuyStates[-1].stop_price
|
||||||
|
|
||||||
# 发送邮件 代码self.turtle.TradeCode, 建议卖出价格price_now,卖出份额self.turtle.IntPositionSize
|
# 发送邮件 代码self.turtle.TradeCode, 建议卖出价格price_now,卖出份额self.turtle.IntPositionSize
|
||||||
subject = "止损卖出"
|
subject = "止损卖出"
|
||||||
body = f"{self.turtle.TradeCode},价格{price_now},份额{self.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().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
@ -561,12 +636,12 @@ class TurtleTrading_OnTime(object):
|
|||||||
|
|
||||||
|
|
||||||
# 成功卖出
|
# 成功卖出
|
||||||
self.turtle.TrigerTime -= sale_shares
|
turtle.TrigerTime -= sale_shares
|
||||||
# 记录self.turtle.BuyStates
|
# 记录self.turtle.BuyStates
|
||||||
available_cash = self.turtle.BuyStates[-1].available_cash + sale_price * sale_share - fee
|
available_cash = turtle.BuyStates[-1].available_cash + sale_price * sale_share - fee
|
||||||
|
|
||||||
# 删除BuyStates中卖出股票的记录
|
# 删除BuyStates中卖出股票的记录
|
||||||
self.turtle.BuyStates = self.turtle.BuyStates[:-sale_shares]
|
turtle.BuyStates = turtle.BuyStates[:-sale_shares]
|
||||||
|
|
||||||
|
|
||||||
sale_this_time = TradeLog(datetime.now().strftime("%Y-%m-%d"),
|
sale_this_time = TradeLog(datetime.now().strftime("%Y-%m-%d"),
|
||||||
@ -574,15 +649,15 @@ class TurtleTrading_OnTime(object):
|
|||||||
sale_price,
|
sale_price,
|
||||||
sale_share,
|
sale_share,
|
||||||
sale_price * sale_share - fee,
|
sale_price * sale_share - fee,
|
||||||
self.turtle.N,
|
turtle.N,
|
||||||
available_cash,
|
available_cash,
|
||||||
all_shares=0,
|
all_shares=0,
|
||||||
all_cost=0,
|
all_cost=0,
|
||||||
Net_value=sale_price * sale_share,
|
Net_value=sale_price * sale_share,
|
||||||
Net_return=abs(self.turtle.Capital - available_cash))
|
Net_return=abs(turtle.Capital - available_cash))
|
||||||
self.turtle.tradeslog.append(sale_this_time)
|
turtle.tradeslog.append(sale_this_time)
|
||||||
|
|
||||||
def out_sale_stock(self, price_now):
|
def out_sale_stock(self, turtle: TurtleTrading, price_now):
|
||||||
"""止盈卖出
|
"""止盈卖出
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -591,7 +666,7 @@ class TurtleTrading_OnTime(object):
|
|||||||
|
|
||||||
# 发送邮件 代码self.turtle.TradeCode, 建议卖出价格price_now,卖出份额self.turtle.IntPositionSize
|
# 发送邮件 代码self.turtle.TradeCode, 建议卖出价格price_now,卖出份额self.turtle.IntPositionSize
|
||||||
subject = "止盈卖出"
|
subject = "止盈卖出"
|
||||||
body = f"{self.turtle.TradeCode},价格{price_now},份额{self.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().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
@ -610,106 +685,106 @@ class TurtleTrading_OnTime(object):
|
|||||||
break
|
break
|
||||||
|
|
||||||
# 成功卖出
|
# 成功卖出
|
||||||
self.turtle.TrigerTime = 0
|
turtle.TrigerTime = 0
|
||||||
# 记录self.turtle.BuyStates
|
# 记录self.turtle.BuyStates
|
||||||
available_cash = self.turtle.BuyStates[-1].available_cash + sale_price * sale_share - fee
|
available_cash = turtle.BuyStates[-1].available_cash + sale_price * sale_share - fee
|
||||||
self.turtle.BuyStates = []
|
turtle.BuyStates = []
|
||||||
|
|
||||||
sale_this_time = TradeLog(datetime.now().strftime("%Y-%m-%d"),
|
sale_this_time = TradeLog(datetime.now().strftime("%Y-%m-%d"),
|
||||||
"止盈",
|
"止盈",
|
||||||
sale_price,
|
sale_price,
|
||||||
sale_share,
|
sale_share,
|
||||||
sale_price * sale_share - fee,
|
sale_price * sale_share - fee,
|
||||||
self.turtle.N,
|
turtle.N,
|
||||||
available_cash,
|
available_cash,
|
||||||
all_shares=0,
|
all_shares=0,
|
||||||
all_cost=0,
|
all_cost=0,
|
||||||
Net_value=sale_price * sale_share,
|
Net_value=sale_price * sale_share,
|
||||||
Net_return=abs(self.turtle.Capital - available_cash))
|
Net_return=abs(turtle.Capital - available_cash))
|
||||||
self.turtle.tradeslog.append(sale_this_time)
|
turtle.tradeslog.append(sale_this_time)
|
||||||
|
|
||||||
def run_short_trading_loop(self, stock_data, etf_data):
|
# def run_short_trading_loop(self, stock_data, etf_data):
|
||||||
|
|
||||||
now = datetime.now().time()
|
# now = datetime.now().time()
|
||||||
# 根据类型获取当前价格
|
# # 根据类型获取当前价格
|
||||||
if self.turtle.type == "stock":
|
# if self.turtle.type == "stock":
|
||||||
self.turtle.PriceNow = float(stock_data.loc[etf_data['代码'] == self.turtle.TradeCode, '最新价'].values[0])
|
# self.turtle.PriceNow = float(stock_data.loc[etf_data['代码'] == self.turtle.TradeCode, '最新价'].values[0])
|
||||||
|
|
||||||
elif self.turtle.type == "etf":
|
# elif self.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])
|
||||||
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])
|
||||||
|
|
||||||
# # 9点30 判断是否跳空高开
|
# # # 9点30 判断是否跳空高开
|
||||||
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 self.turtle.PriceNow > self.turtle.prev_heigh:
|
||||||
self.turtle.is_gap_up = True
|
# self.turtle.is_gap_up = True
|
||||||
|
|
||||||
|
|
||||||
# 判断当前仓位状态并执行相应操作
|
# # 判断当前仓位状态并执行相应操作
|
||||||
if self.turtle.TrigerTime == 0:
|
# if self.turtle.TrigerTime == 0:
|
||||||
# 空仓状态
|
# # 空仓状态
|
||||||
if self.turtle.system1EnterNormal(
|
# if self.turtle.system1EnterNormal(
|
||||||
self.turtle.PriceNow,
|
# self.turtle.PriceNow,
|
||||||
self.turtle.Donchian_20_up,
|
# self.turtle.Donchian_20_up,
|
||||||
self.turtle.BreakOutLog
|
# self.turtle.BreakOutLog
|
||||||
):
|
# ):
|
||||||
self.Buy_stock(self.turtle.PriceNow)
|
# self.Buy_stock(self.turtle.PriceNow)
|
||||||
|
|
||||||
# 突破 记录self.turtle.breakoutlog
|
# # 突破 记录self.turtle.breakoutlog
|
||||||
today = datetime.now().strftime("%Y-%m-%d")
|
# today = datetime.now().strftime("%Y-%m-%d")
|
||||||
breakout_this_time = BreakOutLog(today,
|
# breakout_this_time = BreakOutLog(today,
|
||||||
self.turtle.Donchian_20_up,
|
# self.turtle.Donchian_20_up,
|
||||||
self.turtle.Donchian_20_up - 2 * self.turtle.N,
|
# self.turtle.Donchian_20_up - 2 * self.turtle.N,
|
||||||
'valid',
|
# 'valid',
|
||||||
None)
|
# None)
|
||||||
self.turtle.BreakOutLog.append(breakout_this_time)
|
# self.turtle.BreakOutLog.append(breakout_this_time)
|
||||||
|
|
||||||
elif self.turtle.system1EnterSafe(
|
# elif self.turtle.system1EnterSafe(
|
||||||
self.turtle.PriceNow,
|
# self.turtle.PriceNow,
|
||||||
self.turtle.Donchian_50_up
|
# self.turtle.Donchian_50_up
|
||||||
):
|
# ):
|
||||||
self.Buy_stock(self.turtle.PriceNow)
|
# self.Buy_stock(self.turtle.PriceNow)
|
||||||
|
|
||||||
elif 1 <= self.turtle.TrigerTime <= 3:
|
# elif 1 <= self.turtle.TrigerTime <= 3:
|
||||||
# # 突破状态
|
# # # 突破状态
|
||||||
# if self.turtle.system1EnterNormal(
|
# # if self.turtle.system1EnterNormal(
|
||||||
# self.turtle.PriceNow,
|
# # self.turtle.PriceNow,
|
||||||
# self.turtle.Donchian_20_up,
|
# # self.turtle.Donchian_20_up,
|
||||||
# self.turtle.BreakOutLog
|
# # self.turtle.BreakOutLog
|
||||||
# ):
|
# # ):
|
||||||
# self.Buy_stock(self.turtle.PriceNow)
|
# # self.Buy_stock(self.turtle.PriceNow)
|
||||||
# elif self.turtle.system1EnterSafe(
|
# # elif self.turtle.system1EnterSafe(
|
||||||
# self.turtle.PriceNow,
|
# # self.turtle.PriceNow,
|
||||||
# self.turtle.Donchian_50_up
|
# # self.turtle.Donchian_50_up
|
||||||
# ):
|
# # ):
|
||||||
# self.Buy_stock(self.turtle.PriceNow)
|
# # self.Buy_stock(self.turtle.PriceNow)
|
||||||
|
|
||||||
# 加仓状态
|
# # 加仓状态
|
||||||
if self.turtle.add(self.turtle.PriceNow):
|
# if self.turtle.add(self.turtle.PriceNow):
|
||||||
self.add_stock(self.turtle.PriceNow)
|
# self.add_stock(self.turtle.PriceNow)
|
||||||
|
|
||||||
# 止损状态
|
# # 止损状态
|
||||||
elif self.turtle.system_1_stop(self.turtle.PriceNow):
|
# elif self.turtle.system_1_stop(self.turtle.PriceNow):
|
||||||
self.stop_sale_stock(self.turtle.PriceNow)
|
# self.stop_sale_stock(self.turtle.PriceNow)
|
||||||
|
|
||||||
# 止盈
|
# # 止盈
|
||||||
elif self.turtle.system_1_Out(
|
# elif self.turtle.system_1_Out(
|
||||||
self.turtle.PriceNow,
|
# self.turtle.PriceNow,
|
||||||
self.turtle.Donchian_10_down
|
# self.turtle.Donchian_10_down
|
||||||
):
|
# ):
|
||||||
self.out_sale_stock(self.turtle.PriceNow)
|
# self.out_sale_stock(self.turtle.PriceNow)
|
||||||
|
|
||||||
elif self.turtle.TrigerTime == 4:
|
# elif self.turtle.TrigerTime == 4:
|
||||||
# 满仓 止损 止盈
|
# # 满仓 止损 止盈
|
||||||
if self.turtle.system_1_stop(self.turtle.PriceNow):
|
# if self.turtle.system_1_stop(self.turtle.PriceNow):
|
||||||
self.stop_sale_stock(self.turtle.PriceNow)
|
# self.stop_sale_stock(self.turtle.PriceNow)
|
||||||
elif self.turtle.system_1_Out(
|
# elif self.turtle.system_1_Out(
|
||||||
self.turtle.PriceNow,
|
# self.turtle.PriceNow,
|
||||||
self.turtle.Donchian_10_down
|
# self.turtle.Donchian_10_down
|
||||||
):
|
# ):
|
||||||
self.out_sale_stock(self.turtle.PriceNow)
|
# self.out_sale_stock(self.turtle.PriceNow)
|
||||||
|
|
||||||
# 等待 1 分钟后下一次循环
|
# # 等待 1 分钟后下一次循环
|
||||||
time.sleep(60)
|
# time.sleep(60)
|
||||||
|
|
||||||
def Start_short_system(self):
|
def Start_short_system(self):
|
||||||
"""启动short系统
|
"""启动short系统
|
||||||
@ -767,9 +842,10 @@ class TurtleTrading_OnTime(object):
|
|||||||
# ------------------结束阶段--------------------
|
# ------------------结束阶段--------------------
|
||||||
# 数据库更新当天数据,增加ATR、donchian数据
|
# 数据库更新当天数据,增加ATR、donchian数据
|
||||||
# 直接做个新表
|
# 直接做个新表
|
||||||
mysql_database.delete_table(f"{self.turtle.TradeCode}")
|
for turtle in self.turtles:
|
||||||
self.turtle.get_ready(100)
|
mysql_database.delete_table(f"{turtle.TradeCode}")
|
||||||
time.sleep(16.5*600)
|
turtle.get_ready(100)
|
||||||
|
time.sleep(16.5*600)
|
||||||
|
|
||||||
|
|
||||||
def monitor_all_turtles(self):
|
def monitor_all_turtles(self):
|
||||||
@ -849,7 +925,7 @@ class TurtleTrading_OnTime(object):
|
|||||||
):
|
):
|
||||||
self.start_email_thread(turtle, "止盈", turtle.PriceNow)
|
self.start_email_thread(turtle, "止盈", turtle.PriceNow)
|
||||||
|
|
||||||
def start_email_thread(self, turtle, action, price_now):
|
def start_email_thread(self, turtle:TurtleTrading, action, price_now):
|
||||||
"""启动邮件处理线程"""
|
"""启动邮件处理线程"""
|
||||||
event = threading.Event()
|
event = threading.Event()
|
||||||
self.email_events[turtle.TradeCode] = event
|
self.email_events[turtle.TradeCode] = event
|
||||||
@ -860,17 +936,17 @@ class TurtleTrading_OnTime(object):
|
|||||||
)
|
)
|
||||||
thread.start()
|
thread.start()
|
||||||
|
|
||||||
def handle_email_response(self, turtle, action, price_now, event):
|
def handle_email_response(self, turtle:TurtleTrading, action, price_now, event):
|
||||||
"""处理邮件响应的线程"""
|
"""处理邮件响应的线程"""
|
||||||
# 发送邮件
|
# 发送邮件
|
||||||
if action == "买入":
|
if action == "买入":
|
||||||
self.Buy_stock(price_now)
|
self.Buy_stock(turtle, price_now)
|
||||||
elif action == "加仓":
|
elif action == "加仓":
|
||||||
self.add_stock(price_now)
|
self.add_stock(turtle, price_now)
|
||||||
elif action == "止损":
|
elif action == "止损":
|
||||||
self.stop_sale_stock(price_now)
|
self.stop_sale_stock(turtle, price_now)
|
||||||
elif action == "止盈":
|
elif action == "止盈":
|
||||||
self.out_sale_stock(price_now)
|
self.out_sale_stock(turtle, price_now)
|
||||||
|
|
||||||
# 等待邮件响应
|
# 等待邮件响应
|
||||||
event.wait()
|
event.wait()
|
||||||
|
363
TurtleOnTime.py
363
TurtleOnTime.py
@ -91,7 +91,6 @@ class TurtleTrading(object):
|
|||||||
self.cash = cash
|
self.cash = cash
|
||||||
self.TrigerTime = 0
|
self.TrigerTime = 0
|
||||||
self.BuyStates = list[BuyState]
|
self.BuyStates = list[BuyState]
|
||||||
self.state_file = f"state_{self.TradeCode}.yaml" # 状态文件名
|
|
||||||
|
|
||||||
self.tradeslog = list[TradeLog]
|
self.tradeslog = list[TradeLog]
|
||||||
self.BreakOutLog = list[BreakOutLog]
|
self.BreakOutLog = list[BreakOutLog]
|
||||||
@ -337,40 +336,39 @@ class TurtleTrading(object):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def day_end(self):
|
def day_end(self):
|
||||||
self.save_state() # 每日结束保存状态
|
"""Save current state to YAML file at the end of the day"""
|
||||||
|
# Create state directory if not exists
|
||||||
|
state_dir = "state"
|
||||||
|
if not os.path.exists(state_dir):
|
||||||
|
os.makedirs(state_dir)
|
||||||
|
|
||||||
def save_state(self):
|
# Generate filename with current date
|
||||||
"""保存当前状态到YAML文件"""
|
today = datetime.now().strftime("%Y-%m-%d")
|
||||||
|
filename = os.path.join(state_dir, f"{today}.yaml")
|
||||||
|
|
||||||
|
# Save state to YAML
|
||||||
state_data = {
|
state_data = {
|
||||||
'TrigerTime': self.TrigerTime,
|
"main_state": {
|
||||||
'BuyStates': [vars(bs) for bs in self.BuyStates],
|
"user_email": self.user_email,
|
||||||
'tradeslog': [vars(tl) for tl in self.tradeslog],
|
"email_events": self.email_events,
|
||||||
'BreakOutLog': [vars(bol) for bol in self.BreakOutLog],
|
"turtles": [
|
||||||
'PriceNow': self.PriceNow,
|
{
|
||||||
'Donchian_20_up': self.Donchian_20_up,
|
"TradeCode": t.TradeCode,
|
||||||
'Donchian_10_down': self.Donchian_10_down,
|
"type": t.type,
|
||||||
'Donchian_50_up': self.Donchian_50_up,
|
"riskcoe": t.riskcoe,
|
||||||
'is_gap_up': self.is_gap_up,
|
"Capital": t.Capital,
|
||||||
'prev_heigh': self.prev_heigh
|
"cash": t.cash,
|
||||||
|
"TrigerTime": t.TrigerTime,
|
||||||
|
"BuyStates": [vars(bs) for bs in t.BuyStates],
|
||||||
|
"tradeslog": [vars(tl) for tl in t.tradeslog],
|
||||||
|
"BreakOutLog": [vars(bol) for bol in t.BreakOutLog]
|
||||||
|
} for t in self.turtles
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
with open(self.state_file, 'w') as file:
|
|
||||||
yaml.dump(state_data, file)
|
|
||||||
|
|
||||||
def load_state(self):
|
with open(filename, 'w') as f:
|
||||||
"""从YAML文件加载状态"""
|
yaml.dump(state_data, f)
|
||||||
if os.path.exists(self.state_file):
|
|
||||||
with open(self.state_file, 'r') as file:
|
|
||||||
state_data = yaml.safe_load(file)
|
|
||||||
self.TrigerTime = state_data['TrigerTime']
|
|
||||||
self.BuyStates = [BuyState(**bs) for bs in state_data['BuyStates']]
|
|
||||||
self.tradeslog = [TradeLog(**tl) for tl in state_data['tradeslog']]
|
|
||||||
self.BreakOutLog = [BreakOutLog(**bol) for bol in state_data['BreakOutLog']]
|
|
||||||
self.PriceNow = state_data['PriceNow']
|
|
||||||
self.Donchian_20_up = state_data['Donchian_20_up']
|
|
||||||
self.Donchian_10_down = state_data['Donchian_10_down']
|
|
||||||
self.Donchian_50_up = state_data['Donchian_50_up']
|
|
||||||
self.is_gap_up = state_data['is_gap_up']
|
|
||||||
self.prev_heigh = state_data['prev_heigh']
|
|
||||||
|
|
||||||
class TurtleTrading_OnTime(object):
|
class TurtleTrading_OnTime(object):
|
||||||
''' 实时监测主程序,可以处理多个turtle
|
''' 实时监测主程序,可以处理多个turtle
|
||||||
@ -380,11 +378,51 @@ class TurtleTrading_OnTime(object):
|
|||||||
3、实时监测主流程
|
3、实时监测主流程
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
def load_previous_state(self):
|
||||||
|
"""Load previous state from YAML file if exists"""
|
||||||
|
state_dir = "state"
|
||||||
|
today = datetime.now().strftime("%Y-%m-%d")
|
||||||
|
yesterday = (datetime.now() - timedelta(days=1)).strftime("%Y-%m-%d")
|
||||||
|
filename = os.path.join(state_dir, f"{yesterday}.yaml")
|
||||||
|
|
||||||
|
if os.path.exists(filename):
|
||||||
|
with open(filename, 'r') as f:
|
||||||
|
state_data = yaml.safe_load(f)
|
||||||
|
|
||||||
|
# Restore state
|
||||||
|
for turtle_data in state_data.get('turtles', []):
|
||||||
|
# Find or create TurtleTrading instance
|
||||||
|
turtle = next((t for t in self.turtles if t.TradeCode == turtle_data['TradeCode']), None)
|
||||||
|
if not turtle:
|
||||||
|
# Create new instance if not found (should not happen)
|
||||||
|
turtle = TurtleTrading(**turtle_data)
|
||||||
|
self.turtles.append(turtle)
|
||||||
|
|
||||||
|
# Restore attributes
|
||||||
|
turtle.TradeCode = turtle_data['TradeCode']
|
||||||
|
turtle.type = turtle_data['type']
|
||||||
|
turtle.riskcoe = turtle_data['riskcoe']
|
||||||
|
turtle.Capital = turtle_data['Capital']
|
||||||
|
turtle.cash = turtle_data['cash']
|
||||||
|
turtle.TrigerTime = turtle_data['TrigerTime']
|
||||||
|
turtle.BuyStates = [BuyState(**bs) for bs in turtle_data['BuyStates']]
|
||||||
|
turtle.tradeslog = [TradeLog(**tl) for tl in turtle_data['tradeslog']]
|
||||||
|
turtle.BreakOutLog = [BreakOutLog(**bol) for bol in turtle_data['BreakOutLog']]
|
||||||
|
turtle.PriceNow = turtle_data['PriceNow']
|
||||||
|
turtle.Donchian_20_up = turtle_data['Donchian_20_up']
|
||||||
|
turtle.Donchian_10_down = turtle_data['Donchian_10_down']
|
||||||
|
turtle.Donchian_50_up = turtle_data['Donchian_50_up']
|
||||||
|
turtle.is_gap_up = turtle_data['is_gap_up']
|
||||||
|
turtle.prev_heigh = turtle_data['prev_heigh']
|
||||||
|
|
||||||
def __init__(self, turtles: list[TurtleTrading], user_email):
|
def __init__(self, turtles: list[TurtleTrading], user_email):
|
||||||
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
|
||||||
|
|
||||||
|
# Load previous state from YAML if exists
|
||||||
|
self.load_previous_state()
|
||||||
|
|
||||||
def get_stocks_data(self):
|
def get_stocks_data(self):
|
||||||
"""获取实时股票、基金数据,不保存
|
"""获取实时股票、基金数据,不保存
|
||||||
"""
|
"""
|
||||||
@ -404,13 +442,13 @@ class TurtleTrading_OnTime(object):
|
|||||||
# mysql_database.insert_db(etf_data, "etf_price", True, "代码")
|
# mysql_database.insert_db(etf_data, "etf_price", True, "代码")
|
||||||
return stock_data, etf_data
|
return stock_data, etf_data
|
||||||
|
|
||||||
def Buy_stock(self, price_now):
|
def Buy_stock(self, turtle: TurtleTrading, price_now):
|
||||||
# 发送邮件 代码self.turtle.TradeCode, 建议买入价格price_now,买入份额self.turtle.IntPositionSize
|
# 发送邮件 代码self.turtle.TradeCode, 建议买入价格price_now,买入份额self.turtle.IntPositionSize
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
subject = "买入"
|
subject = "买入"
|
||||||
body = f"{self.turtle.TradeCode},价格{price_now},份额{self.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().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
@ -429,23 +467,23 @@ class TurtleTrading_OnTime(object):
|
|||||||
break
|
break
|
||||||
|
|
||||||
# 成功买入
|
# 成功买入
|
||||||
self.turtle.TrigerTime += 1
|
turtle.TrigerTime += 1
|
||||||
# 记录self.turtle.BuyStates
|
# 记录self.turtle.BuyStates
|
||||||
add_price = buy_price + 1/2 * self.turtle.N
|
add_price = buy_price + 1/2 * turtle.N
|
||||||
stop_price = buy_price - 2 * self.turtle.N
|
stop_price = buy_price - 2 * turtle.N
|
||||||
cost = buy_price * buy_share - fee
|
cost = buy_price * buy_share - fee
|
||||||
available_cash = self.turtle.Capital - cost
|
available_cash = turtle.Capital - cost
|
||||||
|
|
||||||
buy_this_time = BuyState(self.turtle.TrigerTime,
|
buy_this_time = BuyState(turtle.TrigerTime,
|
||||||
buy_price,
|
buy_price,
|
||||||
add_price,
|
add_price,
|
||||||
stop_price,
|
stop_price,
|
||||||
False,
|
False,
|
||||||
buy_share,
|
buy_share,
|
||||||
self.turtle.N,
|
turtle.N,
|
||||||
available_cash)
|
available_cash)
|
||||||
|
|
||||||
self.turtle.BuyStates.append(buy_this_time)
|
turtle.BuyStates.append(buy_this_time)
|
||||||
|
|
||||||
# 记录self.turtle.tradeslog
|
# 记录self.turtle.tradeslog
|
||||||
today = datetime.now().strftime("%Y-%m-%d")
|
today = datetime.now().strftime("%Y-%m-%d")
|
||||||
@ -454,19 +492,19 @@ class TurtleTrading_OnTime(object):
|
|||||||
buy_price,
|
buy_price,
|
||||||
buy_share,
|
buy_share,
|
||||||
cost,
|
cost,
|
||||||
self.turtle.N,
|
turtle.N,
|
||||||
available_cash,
|
available_cash,
|
||||||
all_shares=buy_share,
|
all_shares=buy_share,
|
||||||
all_cost=cost,
|
all_cost=cost,
|
||||||
Net_value=buy_price * buy_share,
|
Net_value=buy_price * buy_share,
|
||||||
Net_return=0)
|
Net_return=0)
|
||||||
self.turtle.tradeslog.append(log_this_time)
|
turtle.tradeslog.append(log_this_time)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def add_stock(self, price_now):
|
def add_stock(self, turtle: TurtleTrading, price_now):
|
||||||
"""加仓
|
"""加仓
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -476,7 +514,7 @@ class TurtleTrading_OnTime(object):
|
|||||||
# 加仓
|
# 加仓
|
||||||
|
|
||||||
subject = "加仓"
|
subject = "加仓"
|
||||||
body = f"{self.turtle.TradeCode},价格{price_now},份额{self.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().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
@ -495,26 +533,26 @@ class TurtleTrading_OnTime(object):
|
|||||||
break
|
break
|
||||||
|
|
||||||
# 成功买入
|
# 成功买入
|
||||||
self.turtle.TrigerTime += 1
|
turtle.TrigerTime += 1
|
||||||
# 记录self.turtle.BuyStates
|
# 记录self.turtle.BuyStates
|
||||||
add_price = buy_price + 1/2 * self.turtle.N
|
add_price = buy_price + 1/2 * turtle.N
|
||||||
stop_price = buy_price - 2 * self.turtle.N
|
stop_price = buy_price - 2 * turtle.N
|
||||||
cost = buy_price * buy_share - fee
|
cost = buy_price * buy_share - fee
|
||||||
available_cash = self.turtle.BuyStates[-1].available_cash - cost
|
available_cash = turtle.BuyStates[-1].available_cash - cost
|
||||||
all_shares = buy_share + self.turtle.BuyStates[-1].all_shares
|
all_shares = buy_share + turtle.BuyStates[-1].all_shares
|
||||||
all_cost = cost + self.turtle.BuyStates[-1].all_cost
|
all_cost = cost + turtle.BuyStates[-1].all_cost
|
||||||
net_value = buy_price * all_shares
|
net_value = buy_price * all_shares
|
||||||
net_return = net_value - all_cost
|
net_return = net_value - all_cost
|
||||||
buy_this_time = BuyState(self.turtle.TrigerTime,
|
buy_this_time = BuyState(turtle.TrigerTime,
|
||||||
buy_price,
|
buy_price,
|
||||||
add_price,
|
add_price,
|
||||||
stop_price,
|
stop_price,
|
||||||
self.turtle.is_gap_up,
|
turtle.is_gap_up,
|
||||||
buy_share,
|
buy_share,
|
||||||
self.turtle.N,
|
turtle.N,
|
||||||
available_cash)
|
available_cash)
|
||||||
|
|
||||||
self.turtle.BuyStates.append(buy_this_time)
|
turtle.BuyStates.append(buy_this_time)
|
||||||
|
|
||||||
|
|
||||||
today = datetime.now().strftime("%Y-%m-%d")
|
today = datetime.now().strftime("%Y-%m-%d")
|
||||||
@ -523,43 +561,43 @@ class TurtleTrading_OnTime(object):
|
|||||||
buy_price,
|
buy_price,
|
||||||
buy_share,
|
buy_share,
|
||||||
cost,
|
cost,
|
||||||
self.turtle.N,
|
turtle.N,
|
||||||
available_cash,
|
available_cash,
|
||||||
all_shares,
|
all_shares,
|
||||||
all_cost,
|
all_cost,
|
||||||
net_value,
|
net_value,
|
||||||
net_return)
|
net_return)
|
||||||
self.turtle.tradeslog.append(log_this_time)
|
turtle.tradeslog.append(log_this_time)
|
||||||
|
|
||||||
# 处理其他次买入的止损价格
|
# 处理其他次买入的止损价格
|
||||||
# 检查BuyStates中有几个gap_up,返回个数和索引
|
# 检查BuyStates中有几个gap_up,返回个数和索引
|
||||||
gap_up_num = 0
|
gap_up_num = 0
|
||||||
gap_up_index = []
|
gap_up_index = []
|
||||||
for i in range(len(self.turtle.BuyStates)):
|
for i in range(len(turtle.BuyStates)):
|
||||||
if self.turtle.BuyStates[i].is_gap_up:
|
if turtle.BuyStates[i].is_gap_up:
|
||||||
gap_up_num += 1
|
gap_up_num += 1
|
||||||
gap_up_index.append(i)
|
gap_up_index.append(i)
|
||||||
if gap_up_num == 0:
|
if gap_up_num == 0:
|
||||||
# 之前BuyStates中的stop_price = stop_price
|
# 之前BuyStates中的stop_price = stop_price
|
||||||
for j in range(len(self.turtle.BuyStates)):
|
for j in range(len(turtle.BuyStates)):
|
||||||
self.turtle.BuyStates[j].stop_price = stop_price
|
turtle.BuyStates[j].stop_price = stop_price
|
||||||
|
|
||||||
if not self.turtle.is_gap_up and gap_up_num == 1:
|
if not turtle.is_gap_up and gap_up_num == 1:
|
||||||
if gap_up_index[0] == 1:
|
if gap_up_index[0] == 1:
|
||||||
number_tobe_change = self.turtle.TrigerTime -1 - gap_up_index[0]
|
number_tobe_change = turtle.TrigerTime -1 - gap_up_index[0]
|
||||||
for k in range(number_tobe_change):
|
for k in range(number_tobe_change):
|
||||||
self.turtle.BuyStates[k+1].stop_price = stop_price
|
turtle.BuyStates[k+1].stop_price = stop_price
|
||||||
|
|
||||||
elif gap_up_index[0] == 2:
|
elif gap_up_index[0] == 2:
|
||||||
self.turtle.BuyStates[2].stop_price = stop_price
|
turtle.BuyStates[2].stop_price = stop_price
|
||||||
|
|
||||||
elif not self.turtle.is_gap_up and gap_up_num == 2:
|
elif not turtle.is_gap_up and gap_up_num == 2:
|
||||||
number_tobe_change = 2
|
number_tobe_change = 2
|
||||||
for k in range(number_tobe_change):
|
for k in range(number_tobe_change):
|
||||||
self.turtle.BuyStates[k+1].stop_price = stop_price
|
turtle.BuyStates[k+1].stop_price = stop_price
|
||||||
|
|
||||||
|
|
||||||
def stop_sale_stock(self, price_now):
|
def stop_sale_stock(self, turtle: TurtleTrading, price_now):
|
||||||
"""止损卖出
|
"""止损卖出
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -568,15 +606,15 @@ class TurtleTrading_OnTime(object):
|
|||||||
|
|
||||||
# 判断需要卖出几份
|
# 判断需要卖出几份
|
||||||
sale_shares = 0
|
sale_shares = 0
|
||||||
for i in range(len(self.turtle.BuyStates)):
|
for i in range(len(turtle.BuyStates)):
|
||||||
if price_now <= self.turtle.BuyStates[i].stop_price:
|
if price_now <= turtle.BuyStates[i].stop_price:
|
||||||
sale_shares += 1
|
sale_shares += 1
|
||||||
break
|
break
|
||||||
# 比较price_now与self.turtle.BuyStates[-1].stop_price
|
# 比较price_now与self.turtle.BuyStates[-1].stop_price
|
||||||
|
|
||||||
# 发送邮件 代码self.turtle.TradeCode, 建议卖出价格price_now,卖出份额self.turtle.IntPositionSize
|
# 发送邮件 代码self.turtle.TradeCode, 建议卖出价格price_now,卖出份额self.turtle.IntPositionSize
|
||||||
subject = "止损卖出"
|
subject = "止损卖出"
|
||||||
body = f"{self.turtle.TradeCode},价格{price_now},份额{self.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().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
@ -596,12 +634,12 @@ class TurtleTrading_OnTime(object):
|
|||||||
|
|
||||||
|
|
||||||
# 成功卖出
|
# 成功卖出
|
||||||
self.turtle.TrigerTime -= sale_shares
|
turtle.TrigerTime -= sale_shares
|
||||||
# 记录self.turtle.BuyStates
|
# 记录self.turtle.BuyStates
|
||||||
available_cash = self.turtle.BuyStates[-1].available_cash + sale_price * sale_share - fee
|
available_cash = turtle.BuyStates[-1].available_cash + sale_price * sale_share - fee
|
||||||
|
|
||||||
# 删除BuyStates中卖出股票的记录
|
# 删除BuyStates中卖出股票的记录
|
||||||
self.turtle.BuyStates = self.turtle.BuyStates[:-sale_shares]
|
turtle.BuyStates = turtle.BuyStates[:-sale_shares]
|
||||||
|
|
||||||
|
|
||||||
sale_this_time = TradeLog(datetime.now().strftime("%Y-%m-%d"),
|
sale_this_time = TradeLog(datetime.now().strftime("%Y-%m-%d"),
|
||||||
@ -609,15 +647,15 @@ class TurtleTrading_OnTime(object):
|
|||||||
sale_price,
|
sale_price,
|
||||||
sale_share,
|
sale_share,
|
||||||
sale_price * sale_share - fee,
|
sale_price * sale_share - fee,
|
||||||
self.turtle.N,
|
turtle.N,
|
||||||
available_cash,
|
available_cash,
|
||||||
all_shares=0,
|
all_shares=0,
|
||||||
all_cost=0,
|
all_cost=0,
|
||||||
Net_value=sale_price * sale_share,
|
Net_value=sale_price * sale_share,
|
||||||
Net_return=abs(self.turtle.Capital - available_cash))
|
Net_return=abs(turtle.Capital - available_cash))
|
||||||
self.turtle.tradeslog.append(sale_this_time)
|
turtle.tradeslog.append(sale_this_time)
|
||||||
|
|
||||||
def out_sale_stock(self, price_now):
|
def out_sale_stock(self, turtle: TurtleTrading, price_now):
|
||||||
"""止盈卖出
|
"""止盈卖出
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -626,7 +664,7 @@ class TurtleTrading_OnTime(object):
|
|||||||
|
|
||||||
# 发送邮件 代码self.turtle.TradeCode, 建议卖出价格price_now,卖出份额self.turtle.IntPositionSize
|
# 发送邮件 代码self.turtle.TradeCode, 建议卖出价格price_now,卖出份额self.turtle.IntPositionSize
|
||||||
subject = "止盈卖出"
|
subject = "止盈卖出"
|
||||||
body = f"{self.turtle.TradeCode},价格{price_now},份额{self.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().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
@ -645,106 +683,106 @@ class TurtleTrading_OnTime(object):
|
|||||||
break
|
break
|
||||||
|
|
||||||
# 成功卖出
|
# 成功卖出
|
||||||
self.turtle.TrigerTime = 0
|
turtle.TrigerTime = 0
|
||||||
# 记录self.turtle.BuyStates
|
# 记录self.turtle.BuyStates
|
||||||
available_cash = self.turtle.BuyStates[-1].available_cash + sale_price * sale_share - fee
|
available_cash = turtle.BuyStates[-1].available_cash + sale_price * sale_share - fee
|
||||||
self.turtle.BuyStates = []
|
turtle.BuyStates = []
|
||||||
|
|
||||||
sale_this_time = TradeLog(datetime.now().strftime("%Y-%m-%d"),
|
sale_this_time = TradeLog(datetime.now().strftime("%Y-%m-%d"),
|
||||||
"止盈",
|
"止盈",
|
||||||
sale_price,
|
sale_price,
|
||||||
sale_share,
|
sale_share,
|
||||||
sale_price * sale_share - fee,
|
sale_price * sale_share - fee,
|
||||||
self.turtle.N,
|
turtle.N,
|
||||||
available_cash,
|
available_cash,
|
||||||
all_shares=0,
|
all_shares=0,
|
||||||
all_cost=0,
|
all_cost=0,
|
||||||
Net_value=sale_price * sale_share,
|
Net_value=sale_price * sale_share,
|
||||||
Net_return=abs(self.turtle.Capital - available_cash))
|
Net_return=abs(turtle.Capital - available_cash))
|
||||||
self.turtle.tradeslog.append(sale_this_time)
|
turtle.tradeslog.append(sale_this_time)
|
||||||
|
|
||||||
def run_short_trading_loop(self, stock_data, etf_data):
|
# def run_short_trading_loop(self, stock_data, etf_data):
|
||||||
|
|
||||||
now = datetime.now().time()
|
# now = datetime.now().time()
|
||||||
# 根据类型获取当前价格
|
# # 根据类型获取当前价格
|
||||||
if self.turtle.type == "stock":
|
# if self.turtle.type == "stock":
|
||||||
self.turtle.PriceNow = float(stock_data.loc[etf_data['代码'] == self.turtle.TradeCode, '最新价'].values[0])
|
# self.turtle.PriceNow = float(stock_data.loc[etf_data['代码'] == self.turtle.TradeCode, '最新价'].values[0])
|
||||||
|
|
||||||
elif self.turtle.type == "etf":
|
# elif self.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])
|
||||||
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])
|
||||||
|
|
||||||
# # 9点30 判断是否跳空高开
|
# # # 9点30 判断是否跳空高开
|
||||||
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 self.turtle.PriceNow > self.turtle.prev_heigh:
|
||||||
self.turtle.is_gap_up = True
|
# self.turtle.is_gap_up = True
|
||||||
|
|
||||||
|
|
||||||
# 判断当前仓位状态并执行相应操作
|
# # 判断当前仓位状态并执行相应操作
|
||||||
if self.turtle.TrigerTime == 0:
|
# if self.turtle.TrigerTime == 0:
|
||||||
# 空仓状态
|
# # 空仓状态
|
||||||
if self.turtle.system1EnterNormal(
|
# if self.turtle.system1EnterNormal(
|
||||||
self.turtle.PriceNow,
|
# self.turtle.PriceNow,
|
||||||
self.turtle.Donchian_20_up,
|
# self.turtle.Donchian_20_up,
|
||||||
self.turtle.BreakOutLog
|
# self.turtle.BreakOutLog
|
||||||
):
|
# ):
|
||||||
self.Buy_stock(self.turtle.PriceNow)
|
# self.Buy_stock(self.turtle.PriceNow)
|
||||||
|
|
||||||
# 突破 记录self.turtle.breakoutlog
|
# # 突破 记录self.turtle.breakoutlog
|
||||||
today = datetime.now().strftime("%Y-%m-%d")
|
# today = datetime.now().strftime("%Y-%m-%d")
|
||||||
breakout_this_time = BreakOutLog(today,
|
# breakout_this_time = BreakOutLog(today,
|
||||||
self.turtle.Donchian_20_up,
|
# self.turtle.Donchian_20_up,
|
||||||
self.turtle.Donchian_20_up - 2 * self.turtle.N,
|
# self.turtle.Donchian_20_up - 2 * self.turtle.N,
|
||||||
'valid',
|
# 'valid',
|
||||||
None)
|
# None)
|
||||||
self.turtle.BreakOutLog.append(breakout_this_time)
|
# self.turtle.BreakOutLog.append(breakout_this_time)
|
||||||
|
|
||||||
elif self.turtle.system1EnterSafe(
|
# elif self.turtle.system1EnterSafe(
|
||||||
self.turtle.PriceNow,
|
# self.turtle.PriceNow,
|
||||||
self.turtle.Donchian_50_up
|
# self.turtle.Donchian_50_up
|
||||||
):
|
# ):
|
||||||
self.Buy_stock(self.turtle.PriceNow)
|
# self.Buy_stock(self.turtle.PriceNow)
|
||||||
|
|
||||||
elif 1 <= self.turtle.TrigerTime <= 3:
|
# elif 1 <= self.turtle.TrigerTime <= 3:
|
||||||
# # 突破状态
|
# # # 突破状态
|
||||||
# if self.turtle.system1EnterNormal(
|
# # if self.turtle.system1EnterNormal(
|
||||||
# self.turtle.PriceNow,
|
# # self.turtle.PriceNow,
|
||||||
# self.turtle.Donchian_20_up,
|
# # self.turtle.Donchian_20_up,
|
||||||
# self.turtle.BreakOutLog
|
# # self.turtle.BreakOutLog
|
||||||
# ):
|
# # ):
|
||||||
# self.Buy_stock(self.turtle.PriceNow)
|
# # self.Buy_stock(self.turtle.PriceNow)
|
||||||
# elif self.turtle.system1EnterSafe(
|
# # elif self.turtle.system1EnterSafe(
|
||||||
# self.turtle.PriceNow,
|
# # self.turtle.PriceNow,
|
||||||
# self.turtle.Donchian_50_up
|
# # self.turtle.Donchian_50_up
|
||||||
# ):
|
# # ):
|
||||||
# self.Buy_stock(self.turtle.PriceNow)
|
# # self.Buy_stock(self.turtle.PriceNow)
|
||||||
|
|
||||||
# 加仓状态
|
# # 加仓状态
|
||||||
if self.turtle.add(self.turtle.PriceNow):
|
# if self.turtle.add(self.turtle.PriceNow):
|
||||||
self.add_stock(self.turtle.PriceNow)
|
# self.add_stock(self.turtle.PriceNow)
|
||||||
|
|
||||||
# 止损状态
|
# # 止损状态
|
||||||
elif self.turtle.system_1_stop(self.turtle.PriceNow):
|
# elif self.turtle.system_1_stop(self.turtle.PriceNow):
|
||||||
self.stop_sale_stock(self.turtle.PriceNow)
|
# self.stop_sale_stock(self.turtle.PriceNow)
|
||||||
|
|
||||||
# 止盈
|
# # 止盈
|
||||||
elif self.turtle.system_1_Out(
|
# elif self.turtle.system_1_Out(
|
||||||
self.turtle.PriceNow,
|
# self.turtle.PriceNow,
|
||||||
self.turtle.Donchian_10_down
|
# self.turtle.Donchian_10_down
|
||||||
):
|
# ):
|
||||||
self.out_sale_stock(self.turtle.PriceNow)
|
# self.out_sale_stock(self.turtle.PriceNow)
|
||||||
|
|
||||||
elif self.turtle.TrigerTime == 4:
|
# elif self.turtle.TrigerTime == 4:
|
||||||
# 满仓 止损 止盈
|
# # 满仓 止损 止盈
|
||||||
if self.turtle.system_1_stop(self.turtle.PriceNow):
|
# if self.turtle.system_1_stop(self.turtle.PriceNow):
|
||||||
self.stop_sale_stock(self.turtle.PriceNow)
|
# self.stop_sale_stock(self.turtle.PriceNow)
|
||||||
elif self.turtle.system_1_Out(
|
# elif self.turtle.system_1_Out(
|
||||||
self.turtle.PriceNow,
|
# self.turtle.PriceNow,
|
||||||
self.turtle.Donchian_10_down
|
# self.turtle.Donchian_10_down
|
||||||
):
|
# ):
|
||||||
self.out_sale_stock(self.turtle.PriceNow)
|
# self.out_sale_stock(self.turtle.PriceNow)
|
||||||
|
|
||||||
# 等待 1 分钟后下一次循环
|
# # 等待 1 分钟后下一次循环
|
||||||
time.sleep(60)
|
# time.sleep(60)
|
||||||
|
|
||||||
def Start_short_system(self):
|
def Start_short_system(self):
|
||||||
"""启动short系统
|
"""启动short系统
|
||||||
@ -802,9 +840,10 @@ class TurtleTrading_OnTime(object):
|
|||||||
# ------------------结束阶段--------------------
|
# ------------------结束阶段--------------------
|
||||||
# 数据库更新当天数据,增加ATR、donchian数据
|
# 数据库更新当天数据,增加ATR、donchian数据
|
||||||
# 直接做个新表
|
# 直接做个新表
|
||||||
mysql_database.delete_table(f"{self.turtle.TradeCode}")
|
for turtle in self.turtles:
|
||||||
self.turtle.get_ready(100)
|
mysql_database.delete_table(f"{turtle.TradeCode}")
|
||||||
time.sleep(16.5*600)
|
turtle.get_ready(100)
|
||||||
|
time.sleep(16.5*600)
|
||||||
|
|
||||||
|
|
||||||
def monitor_all_turtles(self):
|
def monitor_all_turtles(self):
|
||||||
@ -884,7 +923,7 @@ class TurtleTrading_OnTime(object):
|
|||||||
):
|
):
|
||||||
self.start_email_thread(turtle, "止盈", turtle.PriceNow)
|
self.start_email_thread(turtle, "止盈", turtle.PriceNow)
|
||||||
|
|
||||||
def start_email_thread(self, turtle, action, price_now):
|
def start_email_thread(self, turtle:TurtleTrading, action, price_now):
|
||||||
"""启动邮件处理线程"""
|
"""启动邮件处理线程"""
|
||||||
event = threading.Event()
|
event = threading.Event()
|
||||||
self.email_events[turtle.TradeCode] = event
|
self.email_events[turtle.TradeCode] = event
|
||||||
@ -895,17 +934,17 @@ class TurtleTrading_OnTime(object):
|
|||||||
)
|
)
|
||||||
thread.start()
|
thread.start()
|
||||||
|
|
||||||
def handle_email_response(self, turtle, action, price_now, event):
|
def handle_email_response(self, turtle:TurtleTrading, action, price_now, event):
|
||||||
"""处理邮件响应的线程"""
|
"""处理邮件响应的线程"""
|
||||||
# 发送邮件
|
# 发送邮件
|
||||||
if action == "买入":
|
if action == "买入":
|
||||||
self.Buy_stock(price_now)
|
self.Buy_stock(turtle, price_now)
|
||||||
elif action == "加仓":
|
elif action == "加仓":
|
||||||
self.add_stock(price_now)
|
self.add_stock(turtle, price_now)
|
||||||
elif action == "止损":
|
elif action == "止损":
|
||||||
self.stop_sale_stock(price_now)
|
self.stop_sale_stock(turtle, price_now)
|
||||||
elif action == "止盈":
|
elif action == "止盈":
|
||||||
self.out_sale_stock(price_now)
|
self.out_sale_stock(turtle, price_now)
|
||||||
|
|
||||||
# 等待邮件响应
|
# 等待邮件响应
|
||||||
event.wait()
|
event.wait()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user