diff --git a/main.py b/main.py index 0de8fce..8e09f61 100644 --- a/main.py +++ b/main.py @@ -54,6 +54,7 @@ class MexcSpotMarket: 提供获取交易对价格等功能 方法: + - get_exchange_info(symbol): 获取交易对信息 - get_price(symbol): 获取指定交易对的当前价格 """ @@ -61,6 +62,33 @@ class MexcSpotMarket: """初始化市场数据查询接口""" self.market = mexc_spot_v3.mexc_market(config) + def get_exchange_info(self, symbol: str) -> Optional[Dict[str, Any]]: + """ + 获取交易对信息 + + Args: + symbol: 交易对,如 "BTCUSDT" + + Returns: + 交易对信息字典或None(如果失败) + """ + params = {"symbol": symbol} + + try: + logger.info("查询交易对信息: %s", symbol) + exchange_info = self.market.get_exchangeInfo(params) + + if not exchange_info or "symbols" not in exchange_info: + logger.error("获取交易对信息失败: %s", exchange_info) + return None + + logger.info("获取交易对信息成功") + return exchange_info + + except Exception as e: + logger.error("查询交易所信息失败: %s", str(e)) + return None + def get_price(self, symbol: str) -> Optional[float]: """ 获取指定交易对的当前价格 @@ -274,6 +302,44 @@ class MexcSpotTrade: logger.error("记录交易失败: %s", str(e)) return False + def _tool_calculate_quantity( + self, + quantity: float, + price: float, + base_asset_precision: int, + quote_amount_precision: float, + ) -> float: + """ + 调整下单数量以满足最小成交额要求。 + + 策略说明: + - 计算出的quantity如果乘以price后小于交易对的最小成交额(quoteAmountPrecision), + 则将quantity增加一个最小单位(10^(-base_asset_precision)),确保下单金额满足交易所要求。 + + Args: + quantity: 初步计算出的下单数量 + price: 当前价格 + base_asset_precision: 交易对基础资产的小数精度 + quote_amount_precision: 交易对最小成交额 + + Returns: + 满足最小成交额要求的下单数量 + """ + processed_quantity = round(quantity, base_asset_precision) + if processed_quantity * price < quote_amount_precision: + logger.info( + "计算的quantity小于最低要求:%f * %f = %f < %f,进行调整", + processed_quantity, + price, + processed_quantity * price, + quote_amount_precision, + ) + processed_quantity = round( + quantity + 10 ** (-base_asset_precision), base_asset_precision + ) + logger.info("调整后的quantity: %f", processed_quantity) + return processed_quantity + def trade( self, symbol: str, order_type: str, side: str, **kwargs ) -> Optional[Dict[str, Any]]: @@ -322,12 +388,26 @@ class MexcSpotTrade: and "quantity" not in processed_kwargs ): try: + exchange_info = self.market.get_exchange_info(symbol) quote_amount = float(processed_kwargs["quoteOrderQty"]) - price = float(processed_kwargs["price"]) + price = ( + float(current_price) + if not current_price is None + else float(processed_kwargs["price"]) + ) quantity = quote_amount / price - processed_kwargs["quantity"] = str(quantity) + base_asset_precision = int( + exchange_info["symbols"][0]["baseAssetPrecision"] + ) + quote_amount_precision = float( + exchange_info["symbols"][0]["quoteAmountPrecision"] + ) + processed_quantity = self._tool_calculate_quantity( + quantity, price, base_asset_precision, quote_amount_precision + ) + logger.info("根据quoteOrderQty计算quantity: %f", processed_quantity) + processed_kwargs["quantity"] = str(processed_quantity) processed_kwargs.pop("quoteOrderQty") - logger.info("根据quoteOrderQty计算quantity: %f", quantity) except (ValueError, KeyError) as e: logger.error("计算quantity失败: %s", str(e)) return None @@ -484,6 +564,7 @@ class TradingConfig: return today_trades + def git_commit(repo_path: str = ".") -> str: """获取Git仓库版本""" @@ -493,6 +574,7 @@ def git_commit(repo_path: str = ".") -> str: except Exception as _: return None + def main(): """主函数""" @@ -527,7 +609,7 @@ def main(): spot_trader = MexcSpotTrade( config.config_data.get("api", {}), config.config_data.get("symbol_mapping", {}), - os.path.basename(config_file).replace('.json', '') + os.path.basename(config_file).replace(".json", ""), ) today_trades = config.get_today_trades()