This commit is contained in:
summer 2025-07-05 17:31:46 +08:00
parent c4ad8b9398
commit 835f3ddb45
8 changed files with 99 additions and 33 deletions

View File

@ -138,4 +138,7 @@ class state:
return self.data["high_stock_list"] return self.data["high_stock_list"]
def get_hold_list(self): def get_hold_list(self):
return self.data["position_list"] return self.data["position_list"]

View File

@ -289,4 +289,5 @@ class DataHelper:
返回: 返回:
未买入的股票代码列表 未买入的股票代码列表
""" """
return [stock for stock in stock_list if stock not in not_buy_again] return [stock for stock in stock_list if stock not in not_buy_again]

View File

@ -98,6 +98,9 @@ class Logger:
network_config.insert_logs(strategy_id, "critical", message) network_config.insert_logs(strategy_id, "critical", message)
except: except:
pass pass
# # 使用示例 # # 使用示例
# if __name__ == "__main__": # if __name__ == "__main__":
# # 示例1创建新的logger实例 # # 示例1创建新的logger实例

View File

@ -91,4 +91,4 @@ class trade_strategy:
返回: 返回:
若下单成功部分或全部成交返回 True否则返回 False 若下单成功部分或全部成交返回 True否则返回 False
""" """
return self.channel.open_position(security, value) return self.channel.open_position(security, value)

View File

@ -14,7 +14,7 @@ class base_task:
self.strategy_config = self.strategy.get_strategy_config() self.strategy_config = self.strategy.get_strategy_config()
self.configs = self.strategy.get_configs() self.configs = self.strategy.get_configs()
self.log = self.strategy.get_logger() self.log = self.strategy.log
def init(self, context: Any): def init(self, context: Any):
pass pass

View File

@ -31,6 +31,7 @@ class buy_stocks_func_task(base_task):
self.today_trade_switch = self.get_config('today_trade_switch') self.today_trade_switch = self.get_config('today_trade_switch')
self.temp_sells_list = {} self.temp_sells_list = {}
self.temp_buys_list = {} self.temp_buys_list = {}
def run(self, context: Any): def run(self, context: Any):
if not self.today_trade_switch: if not self.today_trade_switch:
@ -48,8 +49,8 @@ class buy_stocks_func_task(base_task):
pos = context.portfolio.positions.get(stock) pos = context.portfolio.positions.get(stock)
self.log.info(f"调仓决策:卖出股票 {stock}") self.log.info(f"调仓决策:卖出股票 {stock}")
# 通过持仓监控器注册卖出请求,而不是直接卖出 # 通过持仓监控器注册卖出请求,而不是直接卖出
self self.sell_request(stock, pos, 'rebalance')
#self.strategy.state.set_sell_request(stock, pos, 'rebalance') # self.strategy.state.set_sell_request(stock, pos, 'rebalance')
self.sell_request(stock, pos, 'rebalance') self.sell_request(stock, pos, 'rebalance')
else: else:
self.log.info(f"调仓决策:继续持有股票 {stock}") self.log.info(f"调仓决策:继续持有股票 {stock}")
@ -59,8 +60,8 @@ class buy_stocks_func_task(base_task):
if buy_targets: if buy_targets:
for stock in buy_targets: for stock in buy_targets:
pos = context.portfolio.positions.get(stock) pos = context.portfolio.positions.get(stock)
#self.strategy.state.set_buy_request(stock, pos, 'buy') # self.strategy.state.set_buy_request(stock, pos, 'buy')
self.buys_request(stock,pos,'buy') self.buys_request(stock, pos, 'buy')
self.log.info(f"调仓决策:将 {len(buy_targets)} 只股票加入待买入队列: {buy_targets}") self.log.info(f"调仓决策:将 {len(buy_targets)} 只股票加入待买入队列: {buy_targets}")
def handle(self, context: Any): def handle(self, context: Any):
@ -71,8 +72,8 @@ class buy_stocks_func_task(base_task):
pass pass
# 这里可以添加任何必要的清理或总结操作 # 这里可以添加任何必要的清理或总结操作
def sell_request(self, stock, data, reason):
def sell_request(self,stock,data,reason):
self.temp_sells_list[f"{stock}_{reason}"] = data self.temp_sells_list[f"{stock}_{reason}"] = data
def buys_request(self,stock,data,reason):
self.temp_buys_list[f"{stock}_{reason}"] = data def buys_request(self, stock, data, reason):
self.temp_buys_list[f"{stock}_{reason}"] = data

View File

@ -10,7 +10,6 @@ class check_positions_stop_loss_task(base_task):
def __init__(self, strategy: trade_strategy): def __init__(self, strategy: trade_strategy):
super().__init__(strategy) super().__init__(strategy)
def config(self, context: Any): def config(self, context: Any):
self.stoploss_switch = self.get_config('stoploss_switch') # 是否启用止损策略 self.stoploss_switch = self.get_config('stoploss_switch') # 是否启用止损策略
@ -23,7 +22,6 @@ class check_positions_stop_loss_task(base_task):
self.index_stocks = self.get_config('index_stocks') # 指数代码 self.index_stocks = self.get_config('index_stocks') # 指数代码
self.temp_sells_list = {} self.temp_sells_list = {}
def run(self, context: Any): def run(self, context: Any):
if len(self.hold_list) == 0: if len(self.hold_list) == 0:
self.log.debug("当前无持仓,跳过止损检查。") self.log.debug("当前无持仓,跳过止损检查。")
@ -37,14 +35,14 @@ class check_positions_stop_loss_task(base_task):
if pos.price >= pos.avg_cost * 2: if pos.price >= pos.avg_cost * 2:
# 通过持仓监控器注册卖出请求,而不是直接卖出 # 通过持仓监控器注册卖出请求,而不是直接卖出
# self.strategy.state.set_sell_request(stock, pos, 'take_profit') # self.strategy.state.set_sell_request(stock, pos, 'take_profit')
self.sell_request(stock,pos,'take_profit') self.sell_request(stock, pos, 'take_profit')
self.log.debug(f"股票 {stock} 实现100%盈利,执行止盈卖出。") self.log.debug(f"股票 {stock} 实现100%盈利,执行止盈卖出。")
elif pos.price < pos.avg_cost * self.stoploss_stock_rate_data: elif pos.price < pos.avg_cost * self.stoploss_stock_rate_data:
# 通过持仓监控器注册卖出请求,而不是直接卖出 # 通过持仓监控器注册卖出请求,而不是直接卖出
self.strategy.state.set_sell_request(stock, pos, 'stop_loss') self.strategy.state.set_sell_request(stock, pos, 'stop_loss')
self.sell_request(stock,pos,'take_profit') self.sell_request(stock, pos, 'take_profit')
self.log.debug(f"股票 {stock} 触及止损阈值,执行卖出。") self.log.debug(f"股票 {stock} 触及止损阈值,执行卖出。")
#self.strategy.state.set_sell_reason("stoploss") # self.strategy.state.set_sell_reason("stoploss")
if self.stoploss_strategy == 2 or self.stoploss_strategy == 3: if self.stoploss_strategy == 2 or self.stoploss_strategy == 3:
# 大盘止损判断,若整体市场跌幅过大则平仓所有股票 # 大盘止损判断,若整体市场跌幅过大则平仓所有股票
@ -60,7 +58,7 @@ class check_positions_stop_loss_task(base_task):
if df is not None and not df.empty: if df is not None and not df.empty:
down_ratio = (df['close'] / df['open']).mean() down_ratio = (df['close'] / df['open']).mean()
if down_ratio <= self.stoploss_market_rate_data: if down_ratio <= self.stoploss_market_rate_data:
#self.strategy.state.set_sell_reason("stoploss") # self.strategy.state.set_sell_reason("stoploss")
self.log.debug(f"市场检测到跌幅(平均跌幅 {down_ratio:.2%}),卖出所有持仓。") self.log.debug(f"市场检测到跌幅(平均跌幅 {down_ratio:.2%}),卖出所有持仓。")
for stock in list(context.portfolio.positions.keys()): for stock in list(context.portfolio.positions.keys()):
pos = context.portfolio.positions[stock] pos = context.portfolio.positions[stock]
@ -79,8 +77,5 @@ class check_positions_stop_loss_task(base_task):
self.log.info("当前卖出请求") self.log.info("当前卖出请求")
pass pass
def sell_request(self, stock, data, reason):
self.temp_sells_list[f"{stock}_{reason}"] = data
def sell_request(self,stock,data,reason):
self.temp_sells_list[f"{stock}_{reason}"] = data

83
test.py
View File

@ -1,13 +1,13 @@
import logging import logging
import os import os
from datetime import timedelta from datetime import timedelta
from datetime import datetime
import requests import requests
from typing import Any, Optional, List, Dict from typing import Any, Optional, List, Dict
import pandas as pd import pandas as pd
from strategy import trade_strategy
class network_config: class network_config:
@ -26,7 +26,8 @@ class network_config:
"strategy_config": "mw1zi3dr5sy03em", # 查看项目URL获取 "strategy_config": "mw1zi3dr5sy03em", # 查看项目URL获取
"strategy_base": "mtvgo6pbrlmbgjc", "strategy_base": "mtvgo6pbrlmbgjc",
"strategy_config_template": "m4nty4o5t6sxzts", "strategy_config_template": "m4nty4o5t6sxzts",
"strategy_logs": "m8ebfypvbfpk38p" "strategy_logs": "m8ebfypvbfpk38p",
"today_state": "mosii8hqry8xx9b"
} }
pass pass
@ -143,6 +144,41 @@ class network_config:
response = requests.post(url, headers=self.headers, data=data) response = requests.post(url, headers=self.headers, data=data)
response.raise_for_status() # 检查错误 response.raise_for_status() # 检查错误
# def update_check(self, id: str, old_value: str, new_value: str):
# """
# 更新网络配置参数
#
# :return:
# """
# PROJECT_ID = self.project_table['strategy_config']
# url = f"{self.BASE_URL}/api/v2/tables/{PROJECT_ID}/records/"
# new_value = {
# "id": id,
# "old_value": old_value,
# "new_value": new_value,
# "create_date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
# }
# update_response = requests.patch(url, headers=self.headers, json=new_value)
# update_response.raise_for_status()
# return update_response.json()
#
# def insert_check(self, strategy_id: str, key: str, value: str):
# """
# 插入网络配置参数
# """
# PROJECT_ID = self.project_table['strategy_config']
# url = f"{self.BASE_URL}/api/v2/tables/{PROJECT_ID}/records"
# data = {
# "strategy_id": strategy_id,
# "type": "check",
# "name": key,
# "new_value": value,
# "create_date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), # 使用当前时间
#
# }
# response = requests.post(url, headers=self.headers, data=data)
# response.raise_for_status() # 检查错误
@staticmethod @staticmethod
def insert_logs(strategy_id: str, log_type: str, log_content: str): def insert_logs(strategy_id: str, log_type: str, log_content: str):
""" """
@ -167,6 +203,29 @@ class network_config:
response = requests.post(url, headers=headers, data=data) response = requests.post(url, headers=headers, data=data)
response.raise_for_status() response.raise_for_status()
@staticmethod
def insert_state(strategy_id: str,state_str:str,trade_date:str):
"""
:param strategy_id:
:param state_str:
:param trade_date:
:return:
"""
PROJECT_ID = "mosii8hqry8xx9b"
url = f"http://101.34.79.70:8081/api/v2/tables/{PROJECT_ID}/records"
data = {
"strategy_id": strategy_id,
"trade_date": trade_date, # 使用当前时间
"state": state_str
}
API_TOKEN = "mgIUTo_BATQnVPE3czsHLOLLgcQmnVv1qs7gJTIO" # 在用户设置中创建
headers = {
"xc-token": API_TOKEN
}
response = requests.post(url, headers=headers, data=data)
response.raise_for_status()
class strategy_config: class strategy_config:
@ -235,12 +294,12 @@ class strategy_config:
id = self.configkey_id.get(key) id = self.configkey_id.get(key)
self.connection.update_config(id, value) self.connection.update_config(id, value)
def get_config(self, key: str):
# if __name__ == "__main__": func = conf.config_type(key)
# config_instance = strategy_config('aaa', '10000000', network_config(), None) return func(key)
from datetime import datetime
class hold_data: class hold_data:
@ -377,6 +436,9 @@ class state:
""" """
return self.data["high_stock_list"] return self.data["high_stock_list"]
def get_hold_list(self):
return self.data["position_list"]
class conf: class conf:
@ -703,6 +765,7 @@ class DataHelper:
return [stock for stock in stock_list if stock not in not_buy_again] return [stock for stock in stock_list if stock not in not_buy_again]
class Logger: class Logger:
""" """
简单的日志操作类支持控制台和文件输出 简单的日志操作类支持控制台和文件输出
@ -796,6 +859,8 @@ class Logger:
network_config.insert_logs(strategy_id, "critical", message) network_config.insert_logs(strategy_id, "critical", message)
except: except:
pass pass
class exchange: class exchange:
def close_positions(self, context: Any, position: Any): def close_positions(self, context: Any, position: Any):
@ -930,7 +995,8 @@ class trade_strategy:
set_option('avoid_future_data', True) set_option('avoid_future_data', True)
# 设置策略基准为上证指数 # 设置策略基准为上证指数
set_benchmark(self.strategy_config.config["benchmark_stock"]) # set_benchmark(self.strategy_config.config["benchmark_stock"])
set_benchmark("000001.XSHG")
# 使用真实市场价格,模拟实际交易 # 使用真实市场价格,模拟实际交易
set_option('use_real_price', True) set_option('use_real_price', True)
# 设置固定滑点,确保价格偏差不大 # 设置固定滑点,确保价格偏差不大
@ -1034,9 +1100,6 @@ class base_task:
return func(self.configs[key]['new_value'], data_params) return func(self.configs[key]['new_value'], data_params)
from kit.kit import DataHelper
from strategy import trade_strategy
from task.base_task import base_task
class check_state_before_task(base_task): class check_state_before_task(base_task):