feat(config): execute all json in config/

This commit is contained in:
2025-07-17 22:24:50 +08:00
parent f7b17d4904
commit bfb88af302
6 changed files with 124 additions and 76 deletions

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
output/ output/
public/ public/
config/
__pycache__/ __pycache__/

View File

@@ -16,7 +16,7 @@ MEXC 交易机器人是一个自动化交易工具,用于在 MEXC 交易所执
## 安装与使用 ## 安装与使用
1. 创建配置文件`trading_config.json` 1. 创建配置文件`config/trading_config.json`(可有多个不同名字的`.json`文件,程序会自动遍历所有)
2. 运行程序: 2. 运行程序:
```bash ```bash
@@ -31,6 +31,11 @@ MEXC 交易机器人是一个自动化交易工具,用于在 MEXC 交易所执
```json ```json
{ {
"api": {
"mexc_host": "https://api.mexc.com",
"api_key": "mxxxxxxxxxx",
"secret_key": "xxxxxxxxxxxxxxxxx"
},
"symbol_mapping": { "symbol_mapping": {
"BTCUSDC": "BTCUSDT" "BTCUSDC": "BTCUSDT"
}, },
@@ -51,12 +56,14 @@ MEXC 交易机器人是一个自动化交易工具,用于在 MEXC 交易所执
### 配置字段详解 ### 配置字段详解
#### 1. 证券代码映射 (`symbol_mapping`) #### 1. API 配置 (`api`)
#### 2. 证券代码映射 (`symbol_mapping`)
- 类型:数组 - 类型:数组
- 描述API 代码: CSV 记录代码,如`"BTCUSDC": "BTCUSDT"`代表向 API 请求`BTCUSDC`,但 CSV 中记录证券代码`BTCUSDT` - 描述API 代码: CSV 记录代码,如`"BTCUSDC": "BTCUSDT"`代表向 API 请求`BTCUSDC`,但 CSV 中记录证券代码`BTCUSDT`
#### 2. 交易列表 (`trades`) #### 3. 交易列表 (`trades`)
- 类型:数组 - 类型:数组
- 描述:包含所有交易指令的列表 - 描述:包含所有交易指令的列表

View File

@@ -1,3 +0,0 @@
mexc_host = "https://api.mexc.com"
api_key = "mx0vglky5BuzlcK5HQ"
secret_key = "e2a0c4737b4643bbac4ad5f8b26dcce2"

View File

@@ -13,7 +13,7 @@ logging.basicConfig(
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def load_config(config_path="trading_config.json"): def load_config(config_path="config/trading_config.json"):
"""加载交易配置文件。 """加载交易配置文件。
Args: Args:
@@ -100,7 +100,9 @@ def generate_ics(config):
date_obj = datetime.strptime(date_str, "%Y-%m-%d").date() date_obj = datetime.strptime(date_str, "%Y-%m-%d").date()
event = create_event(symbol, comment, date_obj, description) event = create_event(symbol, comment, date_obj, description)
cal.add_component(event) cal.add_component(event)
logger.info("已创建项目:%s 交易 (%s) %s", symbol, comment, date_str) logger.info(
"已创建项目:%s 交易 (%s) %s", symbol, comment, date_str
)
except ValueError as ex: except ValueError as ex:
logger.warning("跳过无效日期 %s: %s", date_str, ex) logger.warning("跳过无效日期 %s: %s", date_str, ex)
@@ -121,13 +123,33 @@ def save_ics(calendar, output_path="public/trading.ics"):
def main(): def main():
"""主执行函数。""" """主执行函数遍历config目录下的所有json文件并生成对应的ics文件"""
try: try:
config = load_config() # 遍历config目录下的所有json文件
for filename in os.listdir("config"):
if filename.endswith(".json"):
config_path = os.path.join("config", filename)
try:
# 加载配置
config = load_config(config_path)
# 生成ics文件名保留原文件名只改扩展名
ics_filename = os.path.splitext(filename)[0] + ".ics"
ics_path = os.path.join("public", ics_filename)
# 生成并保存ics文件
calendar = generate_ics(config) calendar = generate_ics(config)
save_ics(calendar) save_ics(calendar, ics_path)
except Exception as ex: # pylint: disable=broad-except
logger.error("生成失败: %s", ex, exc_info=True) logger.info("成功生成: %s%s", config_path, ics_path)
except Exception as ex:
logger.error("处理文件 %s 失败: %s", config_path, ex, exc_info=True)
continue # 继续处理下一个文件
logger.info("所有文件处理完成")
except Exception as ex:
logger.error("程序执行失败: %s", ex, exc_info=True)
raise raise

72
main.py
View File

@@ -55,9 +55,9 @@ class MexcSpotMarket:
- get_price(symbol): 获取指定交易对的当前价格 - get_price(symbol): 获取指定交易对的当前价格
""" """
def __init__(self): def __init__(self, config):
"""初始化市场数据查询接口""" """初始化市场数据查询接口"""
self.market = mexc_spot_v3.mexc_market() self.market = mexc_spot_v3.mexc_market(config)
def get_price(self, symbol: str) -> Optional[float]: def get_price(self, symbol: str) -> Optional[float]:
""" """
@@ -123,12 +123,12 @@ class MexcSpotTrade:
"FILL_OR_KILL": ["quantity", "price"], "FILL_OR_KILL": ["quantity", "price"],
} }
def __init__(self): def __init__(self, config, symbol_mapping):
"""初始化交易机器人""" """初始化交易机器人"""
self.trader = mexc_spot_v3.mexc_trade() self.trader = mexc_spot_v3.mexc_trade(config)
self.market = MexcSpotMarket() self.market = MexcSpotMarket(config)
self.csv_file = "output/mexc_spot_trade.csv" self.csv_file = "output/mexc_spot_trade.csv"
self.symbol_mapping = TradingConfig().config_data.get("symbol_mapping", {}) self.symbol_mapping = symbol_mapping
def _api_get_order(self, symbol: str, order_id: str) -> Optional[Dict[str, Any]]: def _api_get_order(self, symbol: str, order_id: str) -> Optional[Dict[str, Any]]:
""" """
@@ -414,7 +414,7 @@ class TradingConfig:
- _load_config(): 加载JSON配置文件 - _load_config(): 加载JSON配置文件
""" """
def __init__(self, config_file: str = "public/trading_config.json"): def __init__(self, config_file: str = "config/trading_config.json"):
""" """
初始化交易配置 初始化交易配置
@@ -481,36 +481,54 @@ class TradingConfig:
def main(): def main():
"""主函数""" """主函数"""
# 初始化交易配置 # 确保config目录存在
config = TradingConfig() if not os.path.exists("config"):
logger.error("配置目录 config 不存在")
return
# 获取今天需要执行的交易 # 获取config目录下所有json文件
config_files = list(Path("config").glob("*.json"))
if not config_files:
logger.info("配置目录中没有找到任何JSON文件")
return
logger.info("找到 %d 个配置文件需要处理", len(config_files))
for config_file in config_files:
try:
# 提取交易参数
logger.info("处理配置文件: %s", config_file)
config = TradingConfig(str(config_file))
spot_trader = MexcSpotTrade(
config.config_data.get("api", {}),
config.config_data.get("symbol_mapping", {}),
)
today_trades = config.get_today_trades() today_trades = config.get_today_trades()
if not today_trades: if not today_trades:
logger.info("今天没有需要执行的交易") logger.info("%s - 今天没有需要执行的交易", config_file)
return continue
logger.info("今天有 %d 个交易需要执行", len(today_trades)) logger.info("%s - 今天有 %d 个交易需要执行", config_file, len(today_trades))
# 初始化交易类
spot_trader = MexcSpotTrade()
# 执行每个交易
for trade_config in today_trades: for trade_config in today_trades:
try: try:
# 提取交易参数
symbol = trade_config.get("symbol") symbol = trade_config.get("symbol")
order_type = trade_config.get("order_type") order_type = trade_config.get("order_type")
side = trade_config.get("side") side = trade_config.get("side")
params = trade_config.get("params", {}) params = trade_config.get("params", {})
if not all([symbol, order_type, side]): if not all([symbol, order_type, side]):
logger.error("交易配置缺少必要参数: %s", trade_config) logger.error(
"%s - 交易配置缺少必要参数: %s", config_file, trade_config
)
continue continue
logger.info("执行交易: %s %s %s", symbol, order_type, side) logger.info(
logger.debug("交易参数: %s", params) "%s - 执行交易: %s %s %s", config_file, symbol, order_type, side
)
logger.debug("%s - 交易参数: %s", config_file, params)
# 执行交易 # 执行交易
result = spot_trader.trade( result = spot_trader.trade(
@@ -518,15 +536,19 @@ def main():
) )
if result: if result:
logger.info("交易执行成功: %s", result) logger.info("%s - 交易执行成功: %s", config_file, result)
else: else:
logger.error("交易执行失败") logger.error("%s - 交易执行失败", config_file)
except Exception as e: except Exception as e:
logger.error("执行交易时出错: %s", str(e)) logger.error("%s - 执行交易时出错: %s", config_file, str(e))
continue continue
logger.info("执行完毕") except Exception as e:
logger.error("处理配置文件 %s 时出错: %s", config_file, str(e))
continue
logger.info("所有配置文件处理完毕")
if __name__ == "__main__": if __name__ == "__main__":

View File

@@ -2,7 +2,6 @@ import requests
import hmac import hmac
import hashlib import hashlib
from urllib.parse import urlencode, quote from urllib.parse import urlencode, quote
import config
# ServerTime、Signature # ServerTime、Signature
class TOOL(object): class TOOL(object):
@@ -42,9 +41,9 @@ class TOOL(object):
# Market Data # Market Data
class mexc_market(TOOL): class mexc_market(TOOL):
def __init__(self): def __init__(self, config):
self.api = '/api/v3' self.api = '/api/v3'
self.hosts = config.mexc_host self.hosts = config["mexc_host"]
self.method = 'GET' self.method = 'GET'
def get_ping(self): def get_ping(self):
@@ -129,11 +128,11 @@ class mexc_market(TOOL):
# Spot Trade # Spot Trade
class mexc_trade(TOOL): class mexc_trade(TOOL):
def __init__(self): def __init__(self, config):
self.api = '/api/v3' self.api = '/api/v3'
self.hosts = config.mexc_host self.hosts = config["mexc_host"]
self.mexc_key = config.api_key self.mexc_key = config["api_key"]
self.mexc_secret = config.secret_key self.mexc_secret = config["secret_key"]
def get_selfSymbols(self): def get_selfSymbols(self):
"""get currency information""" """get currency information"""
@@ -246,11 +245,11 @@ class mexc_trade(TOOL):
# Wallet # Wallet
class mexc_wallet(TOOL): class mexc_wallet(TOOL):
def __init__(self): def __init__(self, config):
self.api = '/api/v3/capital' self.api = '/api/v3/capital'
self.hosts = config.mexc_host self.hosts = config["mexc_host"]
self.mexc_key = config.api_key self.mexc_key = config["api_key"]
self.mexc_secret = config.secret_key self.mexc_secret = config["secret_key"]
def get_coinlist(self): def get_coinlist(self):
"""get currency information""" """get currency information"""
@@ -368,11 +367,11 @@ class mexc_wallet(TOOL):
# Sub-Account # Sub-Account
class mexc_subaccount(TOOL): class mexc_subaccount(TOOL):
def __init__(self): def __init__(self, config):
self.api = '/api/v3' self.api = '/api/v3'
self.hosts = config.mexc_host self.hosts = config["mexc_host"]
self.mexc_key = config.api_key self.mexc_key = config["api_key"]
self.mexc_secret = config.secret_key self.mexc_secret = config["secret_key"]
def post_virtualSubAccount(self, params): def post_virtualSubAccount(self, params):
"""create a sub-account""" """create a sub-account"""
@@ -427,11 +426,11 @@ class mexc_subaccount(TOOL):
# Rebate # Rebate
class mexc_rebate(TOOL): class mexc_rebate(TOOL):
def __init__(self): def __init__(self, config):
self.api = '/api/v3/rebate' self.api = '/api/v3/rebate'
self.hosts = config.mexc_host self.hosts = config["mexc_host"]
self.mexc_key = config.api_key self.mexc_key = config["api_key"]
self.mexc_secret = config.secret_key self.mexc_secret = config["secret_key"]
def get_taxQuery(self, params=None): def get_taxQuery(self, params=None):
"""get the rebate commission record""" """get the rebate commission record"""
@@ -500,11 +499,11 @@ class mexc_rebate(TOOL):
# WebSocket ListenKey # WebSocket ListenKey
class mexc_listenkey(TOOL): class mexc_listenkey(TOOL):
def __init__(self): def __init__(self, config):
self.api = '/api/v3' self.api = '/api/v3'
self.hosts = config.mexc_host self.hosts = config["mexc_host"]
self.mexc_key = config.api_key self.mexc_key = config["api_key"]
self.mexc_secret = config.secret_key self.mexc_secret = config["secret_key"]
def post_listenKey(self): def post_listenKey(self):
""" generate ListenKey """ """ generate ListenKey """