Spaces:
Runtime error
Runtime error
Update qlib/mcp_output/mcp_plugin/mcp_service.py
Browse files
qlib/mcp_output/mcp_plugin/mcp_service.py
CHANGED
|
@@ -7,33 +7,9 @@ import qlib
|
|
| 7 |
data_dir = os.getenv("QLIB_DATA_DIR", "/app/qlib_data")
|
| 8 |
print(f"Using Qlib data path: {data_dir}")
|
| 9 |
|
|
|
|
| 10 |
qlib.init(provider_uri=data_dir, region="cn")
|
| 11 |
|
| 12 |
-
# 根据你的数据包实际目录结构调整
|
| 13 |
-
instruments_path = os.path.join(data_dir, "instruments") # 或 "cn_data/instruments"
|
| 14 |
-
calendars_path = os.path.join(data_dir, "calendars")
|
| 15 |
-
features_path = os.path.join(data_dir, "features")
|
| 16 |
-
|
| 17 |
-
# 打印 instruments
|
| 18 |
-
if os.path.exists(instruments_path):
|
| 19 |
-
print("\n=== Instruments directory ===")
|
| 20 |
-
for freq in os.listdir(instruments_path):
|
| 21 |
-
freq_path = os.path.join(instruments_path, freq)
|
| 22 |
-
if os.path.isdir(freq_path):
|
| 23 |
-
files = os.listdir(freq_path)
|
| 24 |
-
print(f"{freq}/ : {len(files)} files -> {files[:10]}{'...' if len(files) > 10 else ''}")
|
| 25 |
-
else:
|
| 26 |
-
print("Instruments directory not found!")
|
| 27 |
-
|
| 28 |
-
# 尝试列出 day 级标的
|
| 29 |
-
try:
|
| 30 |
-
instruments = D.list_instruments(freq="day", market="cn")
|
| 31 |
-
print(f"\nNumber of day-frequency instruments: {len(instruments)}")
|
| 32 |
-
print(f"Sample instruments: {instruments[:10]}")
|
| 33 |
-
except Exception as e:
|
| 34 |
-
print("Error listing day-frequency instruments:", e)
|
| 35 |
-
|
| 36 |
-
|
| 37 |
# Path settings
|
| 38 |
source_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), "source")
|
| 39 |
sys.path.insert(0, source_path)
|
|
@@ -55,13 +31,13 @@ from qlib.workflow.task.manage import TaskManager
|
|
| 55 |
mcp = FastMCP("qlib_service")
|
| 56 |
|
| 57 |
|
| 58 |
-
@mcp.tool(name="initialize_exchange", description="Initialize and return an Exchange object for backtesting or trading simulations.")
|
| 59 |
def initialize_exchange(
|
| 60 |
exchange: Optional[str] = None,
|
| 61 |
-
freq: str = "
|
| 62 |
start_time: Optional[str] = None,
|
| 63 |
end_time: Optional[str] = None,
|
| 64 |
-
codes: str = "
|
| 65 |
subscribe_fields: Optional[List[str]] = None,
|
| 66 |
open_cost: float = 0.0015,
|
| 67 |
close_cost: float = 0.0025,
|
|
@@ -72,23 +48,32 @@ def initialize_exchange(
|
|
| 72 |
) -> dict:
|
| 73 |
"""
|
| 74 |
Initialize and return an Exchange object for backtesting or trading simulations.
|
| 75 |
-
|
| 76 |
Parameters:
|
| 77 |
exchange (Optional[str]): Existing exchange name or configuration.
|
| 78 |
-
freq (str): Frequency of data
|
| 79 |
start_time (Optional[str]): Start time for the exchange (e.g., '2020-01-01').
|
| 80 |
end_time (Optional[str]): End time for the exchange (e.g., '2021-01-01').
|
| 81 |
-
codes (str): Instruments string
|
| 82 |
-
subscribe_fields (Optional[List[str]]): Data fields to subscribe to.
|
| 83 |
-
open_cost (float): Open transaction cost as a ratio.
|
| 84 |
-
close_cost (float): Close transaction cost as a ratio.
|
| 85 |
-
min_cost (float): Minimum transaction cost.
|
| 86 |
-
limit_threshold (Optional[float]): Price movement limits.
|
| 87 |
-
deal_price (Optional[str]): Price configuration.
|
| 88 |
extra_kwargs (Optional[Dict[str, Any]]): Additional keyword arguments as a dictionary.
|
| 89 |
-
|
| 90 |
Returns:
|
| 91 |
-
dict: A dictionary containing success, result, or error
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 92 |
"""
|
| 93 |
try:
|
| 94 |
# Handle None defaults
|
|
@@ -97,6 +82,14 @@ def initialize_exchange(
|
|
| 97 |
if extra_kwargs is None:
|
| 98 |
extra_kwargs = {}
|
| 99 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 100 |
exchange_obj = get_exchange(
|
| 101 |
exchange=exchange,
|
| 102 |
freq=freq,
|
|
@@ -111,7 +104,11 @@ def initialize_exchange(
|
|
| 111 |
deal_price=deal_price,
|
| 112 |
**extra_kwargs,
|
| 113 |
)
|
| 114 |
-
return {
|
|
|
|
|
|
|
|
|
|
|
|
|
| 115 |
except Exception as e:
|
| 116 |
return {"success": False, "error": str(e)}
|
| 117 |
|
|
@@ -126,16 +123,24 @@ def create_account(
|
|
| 126 |
) -> dict:
|
| 127 |
"""
|
| 128 |
Create and initialize an Account instance for trading simulations.
|
| 129 |
-
|
| 130 |
Parameters:
|
| 131 |
start_time (str): Start time of the benchmark (e.g., '2020-01-01').
|
| 132 |
end_time (str): End time of the benchmark (e.g., '2021-01-01').
|
| 133 |
-
benchmark (str): Benchmark for
|
| 134 |
-
account (float): Initial cash amount.
|
| 135 |
pos_type (str): Type of position to use (default: "Position").
|
| 136 |
-
|
| 137 |
Returns:
|
| 138 |
-
dict: A dictionary containing success, result, or error
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 139 |
"""
|
| 140 |
try:
|
| 141 |
account_obj = create_account_instance(
|
|
@@ -145,7 +150,11 @@ def create_account(
|
|
| 145 |
account=account,
|
| 146 |
pos_type=pos_type,
|
| 147 |
)
|
| 148 |
-
return {
|
|
|
|
|
|
|
|
|
|
|
|
|
| 149 |
except Exception as e:
|
| 150 |
return {"success": False, "error": str(e)}
|
| 151 |
|
|
@@ -163,19 +172,22 @@ def initialize_strategy_executor(
|
|
| 163 |
) -> dict:
|
| 164 |
"""
|
| 165 |
Initialize and configure a trading strategy and its executor.
|
| 166 |
-
|
| 167 |
Parameters:
|
| 168 |
start_time (str): Start time for the strategy (e.g., '2020-01-01').
|
| 169 |
end_time (str): End time for the strategy (e.g., '2021-01-01').
|
| 170 |
-
strategy (dict): Strategy configuration.
|
|
|
|
| 171 |
executor (dict): Executor configuration.
|
| 172 |
-
|
| 173 |
-
|
| 174 |
-
|
|
|
|
|
|
|
| 175 |
pos_type (str): Type of position to use (default: "Position").
|
| 176 |
-
|
| 177 |
Returns:
|
| 178 |
-
dict: A dictionary containing success, result, or error
|
| 179 |
"""
|
| 180 |
try:
|
| 181 |
strategy_executor = get_strategy_executor(
|
|
@@ -188,7 +200,11 @@ def initialize_strategy_executor(
|
|
| 188 |
exchange_kwargs=exchange_kwargs,
|
| 189 |
pos_type=pos_type,
|
| 190 |
)
|
| 191 |
-
return {
|
|
|
|
|
|
|
|
|
|
|
|
|
| 192 |
except Exception as e:
|
| 193 |
return {"success": False, "error": str(e)}
|
| 194 |
|
|
@@ -206,21 +222,39 @@ def run_backtest(
|
|
| 206 |
) -> dict:
|
| 207 |
"""
|
| 208 |
Perform a backtest to evaluate a trading strategy.
|
| 209 |
-
|
| 210 |
Parameters:
|
| 211 |
start_time (str): Start time for the backtest (e.g., '2020-01-01').
|
| 212 |
end_time (str): End time for the backtest (e.g., '2021-01-01').
|
| 213 |
strategy (dict): Strategy configuration.
|
|
|
|
| 214 |
executor (dict): Executor configuration.
|
| 215 |
-
|
| 216 |
-
|
| 217 |
-
|
|
|
|
|
|
|
| 218 |
pos_type (str): Type of position to use (default: "Position").
|
| 219 |
-
|
| 220 |
Returns:
|
| 221 |
-
dict: A dictionary containing success,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 222 |
"""
|
| 223 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 224 |
portfolio_metrics, trading_indicators = backtest(
|
| 225 |
start_time=start_time,
|
| 226 |
end_time=end_time,
|
|
@@ -238,7 +272,11 @@ def run_backtest(
|
|
| 238 |
"trading_indicators": trading_indicators.to_dict() if hasattr(trading_indicators, 'to_dict') else str(trading_indicators)
|
| 239 |
}
|
| 240 |
|
| 241 |
-
return {
|
|
|
|
|
|
|
|
|
|
|
|
|
| 242 |
except Exception as e:
|
| 243 |
return {"success": False, "error": str(e)}
|
| 244 |
|
|
@@ -256,7 +294,7 @@ def collect_trade_data(
|
|
| 256 |
) -> dict:
|
| 257 |
"""
|
| 258 |
Collect trade decision data for reinforcement learning training.
|
| 259 |
-
|
| 260 |
Parameters:
|
| 261 |
start_time (str): Start time for data collection (e.g., '2020-01-01').
|
| 262 |
end_time (str): End time for data collection (e.g., '2021-01-01').
|
|
@@ -264,13 +302,17 @@ def collect_trade_data(
|
|
| 264 |
executor (dict): Executor configuration.
|
| 265 |
benchmark (str): Benchmark identifier.
|
| 266 |
account (float): Initial cash amount.
|
| 267 |
-
exchange_kwargs (dict): Exchange-specific settings.
|
| 268 |
pos_type (str): Type of position to use (default: "Position").
|
| 269 |
-
|
| 270 |
Returns:
|
| 271 |
-
dict: A dictionary containing success,
|
| 272 |
"""
|
| 273 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 274 |
data_generator = collect_data(
|
| 275 |
start_time=start_time,
|
| 276 |
end_time=end_time,
|
|
@@ -283,7 +325,11 @@ def collect_trade_data(
|
|
| 283 |
return_value=None,
|
| 284 |
)
|
| 285 |
data = list(data_generator)
|
| 286 |
-
return {
|
|
|
|
|
|
|
|
|
|
|
|
|
| 287 |
except Exception as e:
|
| 288 |
return {"success": False, "error": str(e)}
|
| 289 |
|
|
@@ -292,16 +338,64 @@ def collect_trade_data(
|
|
| 292 |
def format_trade_decisions(decisions: List[str]) -> dict:
|
| 293 |
"""
|
| 294 |
Format trade decisions into a hierarchical structure.
|
| 295 |
-
|
| 296 |
Parameters:
|
| 297 |
decisions (List[str]): List of trade decisions as strings.
|
| 298 |
-
|
| 299 |
Returns:
|
| 300 |
-
dict: A dictionary containing success,
|
| 301 |
"""
|
| 302 |
try:
|
| 303 |
formatted_decisions = format_decisions(decisions)
|
| 304 |
-
return {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 305 |
except Exception as e:
|
| 306 |
return {"success": False, "error": str(e)}
|
| 307 |
|
|
@@ -309,7 +403,7 @@ def format_trade_decisions(decisions: List[str]) -> dict:
|
|
| 309 |
def create_app() -> FastMCP:
|
| 310 |
"""
|
| 311 |
Create and return the FastMCP application instance.
|
| 312 |
-
|
| 313 |
Returns:
|
| 314 |
FastMCP: The FastMCP application instance.
|
| 315 |
"""
|
|
|
|
| 7 |
data_dir = os.getenv("QLIB_DATA_DIR", "/app/qlib_data")
|
| 8 |
print(f"Using Qlib data path: {data_dir}")
|
| 9 |
|
| 10 |
+
# 初始化 qlib,使用 day_future 作为默认频率
|
| 11 |
qlib.init(provider_uri=data_dir, region="cn")
|
| 12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
# Path settings
|
| 14 |
source_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), "source")
|
| 15 |
sys.path.insert(0, source_path)
|
|
|
|
| 31 |
mcp = FastMCP("qlib_service")
|
| 32 |
|
| 33 |
|
| 34 |
+
@mcp.tool(name="initialize_exchange", description="Initialize and return an Exchange object for backtesting or trading simulations. Uses day_future frequency by default to match available data.")
|
| 35 |
def initialize_exchange(
|
| 36 |
exchange: Optional[str] = None,
|
| 37 |
+
freq: str = "day_future", # 修改默认值为 day_future
|
| 38 |
start_time: Optional[str] = None,
|
| 39 |
end_time: Optional[str] = None,
|
| 40 |
+
codes: str = "csi300", # 修改默认值为 csi300(更常用)
|
| 41 |
subscribe_fields: Optional[List[str]] = None,
|
| 42 |
open_cost: float = 0.0015,
|
| 43 |
close_cost: float = 0.0025,
|
|
|
|
| 48 |
) -> dict:
|
| 49 |
"""
|
| 50 |
Initialize and return an Exchange object for backtesting or trading simulations.
|
| 51 |
+
|
| 52 |
Parameters:
|
| 53 |
exchange (Optional[str]): Existing exchange name or configuration.
|
| 54 |
+
freq (str): Frequency of data. Default is 'day_future' (available: 'day_future').
|
| 55 |
start_time (Optional[str]): Start time for the exchange (e.g., '2020-01-01').
|
| 56 |
end_time (Optional[str]): End time for the exchange (e.g., '2021-01-01').
|
| 57 |
+
codes (str): Instruments string. Available options: 'all', 'csi300', 'csi500', 'csi800', 'csi1000', 'csiall'. Default: 'csi300'.
|
| 58 |
+
subscribe_fields (Optional[List[str]]): Data fields to subscribe to (e.g., ['$close', '$volume', '$open', '$high', '$low']).
|
| 59 |
+
open_cost (float): Open transaction cost as a ratio (default: 0.0015 = 0.15%).
|
| 60 |
+
close_cost (float): Close transaction cost as a ratio (default: 0.0025 = 0.25%).
|
| 61 |
+
min_cost (float): Minimum transaction cost in currency units (default: 5.0).
|
| 62 |
+
limit_threshold (Optional[float]): Price movement limits (e.g., 0.095 for 9.5% limit).
|
| 63 |
+
deal_price (Optional[str]): Price configuration for order execution.
|
| 64 |
extra_kwargs (Optional[Dict[str, Any]]): Additional keyword arguments as a dictionary.
|
| 65 |
+
|
| 66 |
Returns:
|
| 67 |
+
dict: A dictionary containing success status, result, or error information.
|
| 68 |
+
|
| 69 |
+
Example:
|
| 70 |
+
initialize_exchange(
|
| 71 |
+
freq="day_future",
|
| 72 |
+
start_time="2020-01-01",
|
| 73 |
+
end_time="2021-12-31",
|
| 74 |
+
codes="csi300",
|
| 75 |
+
subscribe_fields=["$close", "$volume"]
|
| 76 |
+
)
|
| 77 |
"""
|
| 78 |
try:
|
| 79 |
# Handle None defaults
|
|
|
|
| 82 |
if extra_kwargs is None:
|
| 83 |
extra_kwargs = {}
|
| 84 |
|
| 85 |
+
# 验证 codes 参数
|
| 86 |
+
valid_codes = ['all', 'csi300', 'csi500', 'csi800', 'csi1000', 'csiall']
|
| 87 |
+
if codes not in valid_codes:
|
| 88 |
+
return {
|
| 89 |
+
"success": False,
|
| 90 |
+
"error": f"Invalid codes parameter. Available options: {', '.join(valid_codes)}"
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
exchange_obj = get_exchange(
|
| 94 |
exchange=exchange,
|
| 95 |
freq=freq,
|
|
|
|
| 104 |
deal_price=deal_price,
|
| 105 |
**extra_kwargs,
|
| 106 |
)
|
| 107 |
+
return {
|
| 108 |
+
"success": True,
|
| 109 |
+
"result": str(exchange_obj),
|
| 110 |
+
"message": f"Exchange initialized successfully with freq={freq}, codes={codes}"
|
| 111 |
+
}
|
| 112 |
except Exception as e:
|
| 113 |
return {"success": False, "error": str(e)}
|
| 114 |
|
|
|
|
| 123 |
) -> dict:
|
| 124 |
"""
|
| 125 |
Create and initialize an Account instance for trading simulations.
|
| 126 |
+
|
| 127 |
Parameters:
|
| 128 |
start_time (str): Start time of the benchmark (e.g., '2020-01-01').
|
| 129 |
end_time (str): End time of the benchmark (e.g., '2021-01-01').
|
| 130 |
+
benchmark (str): Benchmark for performance comparison (e.g., 'SH000300' for CSI300, 'SH000905' for CSI500).
|
| 131 |
+
account (float): Initial cash amount (e.g., 1000000 for 1 million).
|
| 132 |
pos_type (str): Type of position to use (default: "Position").
|
| 133 |
+
|
| 134 |
Returns:
|
| 135 |
+
dict: A dictionary containing success status, result, or error information.
|
| 136 |
+
|
| 137 |
+
Example:
|
| 138 |
+
create_account(
|
| 139 |
+
start_time="2020-01-01",
|
| 140 |
+
end_time="2021-12-31",
|
| 141 |
+
benchmark="SH000300",
|
| 142 |
+
account=1000000.0
|
| 143 |
+
)
|
| 144 |
"""
|
| 145 |
try:
|
| 146 |
account_obj = create_account_instance(
|
|
|
|
| 150 |
account=account,
|
| 151 |
pos_type=pos_type,
|
| 152 |
)
|
| 153 |
+
return {
|
| 154 |
+
"success": True,
|
| 155 |
+
"result": str(account_obj),
|
| 156 |
+
"message": f"Account created successfully with initial capital: {account}"
|
| 157 |
+
}
|
| 158 |
except Exception as e:
|
| 159 |
return {"success": False, "error": str(e)}
|
| 160 |
|
|
|
|
| 172 |
) -> dict:
|
| 173 |
"""
|
| 174 |
Initialize and configure a trading strategy and its executor.
|
| 175 |
+
|
| 176 |
Parameters:
|
| 177 |
start_time (str): Start time for the strategy (e.g., '2020-01-01').
|
| 178 |
end_time (str): End time for the strategy (e.g., '2021-01-01').
|
| 179 |
+
strategy (dict): Strategy configuration with class and module info.
|
| 180 |
+
Example: {"class": "TopkDropoutStrategy", "module_path": "qlib.contrib.strategy", "kwargs": {"topk": 30, "n_drop": 5}}
|
| 181 |
executor (dict): Executor configuration.
|
| 182 |
+
Example: {"class": "SimulatorExecutor", "module_path": "qlib.backtest.executor", "kwargs": {"time_per_step": "day"}}
|
| 183 |
+
benchmark (str): Benchmark identifier (e.g., 'SH000300' for CSI300).
|
| 184 |
+
account (float): Initial cash amount (e.g., 1000000).
|
| 185 |
+
exchange_kwargs (dict): Exchange-specific settings. Should include 'freq' and 'codes'.
|
| 186 |
+
Example: {"freq": "day_future", "codes": "csi300", "start_time": "2020-01-01", "end_time": "2021-12-31"}
|
| 187 |
pos_type (str): Type of position to use (default: "Position").
|
| 188 |
+
|
| 189 |
Returns:
|
| 190 |
+
dict: A dictionary containing success status, result, or error information.
|
| 191 |
"""
|
| 192 |
try:
|
| 193 |
strategy_executor = get_strategy_executor(
|
|
|
|
| 200 |
exchange_kwargs=exchange_kwargs,
|
| 201 |
pos_type=pos_type,
|
| 202 |
)
|
| 203 |
+
return {
|
| 204 |
+
"success": True,
|
| 205 |
+
"result": str(strategy_executor),
|
| 206 |
+
"message": "Strategy executor initialized successfully"
|
| 207 |
+
}
|
| 208 |
except Exception as e:
|
| 209 |
return {"success": False, "error": str(e)}
|
| 210 |
|
|
|
|
| 222 |
) -> dict:
|
| 223 |
"""
|
| 224 |
Perform a backtest to evaluate a trading strategy.
|
| 225 |
+
|
| 226 |
Parameters:
|
| 227 |
start_time (str): Start time for the backtest (e.g., '2020-01-01').
|
| 228 |
end_time (str): End time for the backtest (e.g., '2021-01-01').
|
| 229 |
strategy (dict): Strategy configuration.
|
| 230 |
+
Example: {"class": "TopkDropoutStrategy", "module_path": "qlib.contrib.strategy", "kwargs": {"topk": 30, "n_drop": 5}}
|
| 231 |
executor (dict): Executor configuration.
|
| 232 |
+
Example: {"class": "SimulatorExecutor", "module_path": "qlib.backtest.executor", "kwargs": {"time_per_step": "day"}}
|
| 233 |
+
benchmark (str): Benchmark identifier (e.g., 'SH000300' for CSI300, 'SH000905' for CSI500).
|
| 234 |
+
account (float): Initial cash amount (e.g., 1000000).
|
| 235 |
+
exchange_kwargs (dict): Exchange-specific settings. Must include 'freq' as 'day_future' and valid 'codes'.
|
| 236 |
+
Example: {"freq": "day_future", "codes": "csi300", "open_cost": 0.0015, "close_cost": 0.0025, "min_cost": 5}
|
| 237 |
pos_type (str): Type of position to use (default: "Position").
|
| 238 |
+
|
| 239 |
Returns:
|
| 240 |
+
dict: A dictionary containing success status, portfolio metrics, trading indicators, or error information.
|
| 241 |
+
|
| 242 |
+
Example:
|
| 243 |
+
run_backtest(
|
| 244 |
+
start_time="2020-01-01",
|
| 245 |
+
end_time="2021-12-31",
|
| 246 |
+
strategy={"class": "TopkDropoutStrategy", "module_path": "qlib.contrib.strategy", "kwargs": {"topk": 30}},
|
| 247 |
+
executor={"class": "SimulatorExecutor", "module_path": "qlib.backtest.executor"},
|
| 248 |
+
benchmark="SH000300",
|
| 249 |
+
account=1000000,
|
| 250 |
+
exchange_kwargs={"freq": "day_future", "codes": "csi300"}
|
| 251 |
+
)
|
| 252 |
"""
|
| 253 |
try:
|
| 254 |
+
# 确保 exchange_kwargs 中包含正确的 freq
|
| 255 |
+
if 'freq' not in exchange_kwargs:
|
| 256 |
+
exchange_kwargs['freq'] = 'day_future'
|
| 257 |
+
|
| 258 |
portfolio_metrics, trading_indicators = backtest(
|
| 259 |
start_time=start_time,
|
| 260 |
end_time=end_time,
|
|
|
|
| 272 |
"trading_indicators": trading_indicators.to_dict() if hasattr(trading_indicators, 'to_dict') else str(trading_indicators)
|
| 273 |
}
|
| 274 |
|
| 275 |
+
return {
|
| 276 |
+
"success": True,
|
| 277 |
+
"result": result,
|
| 278 |
+
"message": "Backtest completed successfully"
|
| 279 |
+
}
|
| 280 |
except Exception as e:
|
| 281 |
return {"success": False, "error": str(e)}
|
| 282 |
|
|
|
|
| 294 |
) -> dict:
|
| 295 |
"""
|
| 296 |
Collect trade decision data for reinforcement learning training.
|
| 297 |
+
|
| 298 |
Parameters:
|
| 299 |
start_time (str): Start time for data collection (e.g., '2020-01-01').
|
| 300 |
end_time (str): End time for data collection (e.g., '2021-01-01').
|
|
|
|
| 302 |
executor (dict): Executor configuration.
|
| 303 |
benchmark (str): Benchmark identifier.
|
| 304 |
account (float): Initial cash amount.
|
| 305 |
+
exchange_kwargs (dict): Exchange-specific settings. Should use 'freq': 'day_future'.
|
| 306 |
pos_type (str): Type of position to use (default: "Position").
|
| 307 |
+
|
| 308 |
Returns:
|
| 309 |
+
dict: A dictionary containing success status, collected data, or error information.
|
| 310 |
"""
|
| 311 |
try:
|
| 312 |
+
# 确保使用正确的 freq
|
| 313 |
+
if 'freq' not in exchange_kwargs:
|
| 314 |
+
exchange_kwargs['freq'] = 'day_future'
|
| 315 |
+
|
| 316 |
data_generator = collect_data(
|
| 317 |
start_time=start_time,
|
| 318 |
end_time=end_time,
|
|
|
|
| 325 |
return_value=None,
|
| 326 |
)
|
| 327 |
data = list(data_generator)
|
| 328 |
+
return {
|
| 329 |
+
"success": True,
|
| 330 |
+
"result": [str(item) for item in data],
|
| 331 |
+
"message": f"Trade data collected successfully. Total records: {len(data)}"
|
| 332 |
+
}
|
| 333 |
except Exception as e:
|
| 334 |
return {"success": False, "error": str(e)}
|
| 335 |
|
|
|
|
| 338 |
def format_trade_decisions(decisions: List[str]) -> dict:
|
| 339 |
"""
|
| 340 |
Format trade decisions into a hierarchical structure.
|
| 341 |
+
|
| 342 |
Parameters:
|
| 343 |
decisions (List[str]): List of trade decisions as strings.
|
| 344 |
+
|
| 345 |
Returns:
|
| 346 |
+
dict: A dictionary containing success status, formatted decisions, or error information.
|
| 347 |
"""
|
| 348 |
try:
|
| 349 |
formatted_decisions = format_decisions(decisions)
|
| 350 |
+
return {
|
| 351 |
+
"success": True,
|
| 352 |
+
"result": str(formatted_decisions),
|
| 353 |
+
"message": "Decisions formatted successfully"
|
| 354 |
+
}
|
| 355 |
+
except Exception as e:
|
| 356 |
+
return {"success": False, "error": str(e)}
|
| 357 |
+
|
| 358 |
+
|
| 359 |
+
@mcp.tool(name="get_available_instruments", description="Get information about available instrument pools in the dataset.")
|
| 360 |
+
def get_available_instruments() -> dict:
|
| 361 |
+
"""
|
| 362 |
+
Get information about available instrument pools in the dataset.
|
| 363 |
+
|
| 364 |
+
Returns:
|
| 365 |
+
dict: A dictionary containing available instrument pools and their descriptions.
|
| 366 |
+
"""
|
| 367 |
+
try:
|
| 368 |
+
instruments_info = {
|
| 369 |
+
"available_pools": [
|
| 370 |
+
"all",
|
| 371 |
+
"csi300", # 沪深300指数成分股
|
| 372 |
+
"csi500", # 中证500指数成分股
|
| 373 |
+
"csi800", # 中证800指数成分股
|
| 374 |
+
"csi1000", # 中证1000指数成分股
|
| 375 |
+
"csiall" # 所有中证指数成分股
|
| 376 |
+
],
|
| 377 |
+
"descriptions": {
|
| 378 |
+
"all": "All available stocks in the dataset",
|
| 379 |
+
"csi300": "CSI 300 Index constituents (top 300 stocks by market cap)",
|
| 380 |
+
"csi500": "CSI 500 Index constituents (mid-cap stocks)",
|
| 381 |
+
"csi800": "CSI 800 Index constituents (CSI 300 + CSI 500)",
|
| 382 |
+
"csi1000": "CSI 1000 Index constituents (small-cap stocks)",
|
| 383 |
+
"csiall": "All CSI Index constituents"
|
| 384 |
+
},
|
| 385 |
+
"benchmarks": {
|
| 386 |
+
"csi300": "SH000300",
|
| 387 |
+
"csi500": "SH000905",
|
| 388 |
+
"csi800": "SH000906",
|
| 389 |
+
"csi1000": "SH000852"
|
| 390 |
+
},
|
| 391 |
+
"frequency": "day_future",
|
| 392 |
+
"data_directory": data_dir
|
| 393 |
+
}
|
| 394 |
+
return {
|
| 395 |
+
"success": True,
|
| 396 |
+
"result": instruments_info,
|
| 397 |
+
"message": "Available instruments information retrieved successfully"
|
| 398 |
+
}
|
| 399 |
except Exception as e:
|
| 400 |
return {"success": False, "error": str(e)}
|
| 401 |
|
|
|
|
| 403 |
def create_app() -> FastMCP:
|
| 404 |
"""
|
| 405 |
Create and return the FastMCP application instance.
|
| 406 |
+
|
| 407 |
Returns:
|
| 408 |
FastMCP: The FastMCP application instance.
|
| 409 |
"""
|