strategy.py 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. """
  4. 交易策略模块
  5. 实现基于Lighter和Binance价差的交易策略
  6. """
  7. import logging
  8. from enum import Enum
  9. from datetime import datetime
  10. import os
  11. import lighter
  12. import json
  13. import time
  14. # 配置日志
  15. logs_dir = "logs"
  16. if not os.path.exists(logs_dir):
  17. os.makedirs(logs_dir)
  18. logger = logging.getLogger("strategy")
  19. class StrategyState(Enum):
  20. """策略状态枚举"""
  21. WAITING_INIT = 1 # 等待初始化
  22. IDLE_MONITORING = 2 # 空闲状态监听价差
  23. EXECUTING_TRADE = 3 # 价差达成触发交易
  24. WAITING_CONVERGENCE = 4 # 交易完成等待价差收敛
  25. CLOSING_POSITION = 5 # 收敛完成进行平仓
  26. POSITION_CLOSED = 6 # 平仓完成
  27. class TradingStrategy:
  28. """交易策略类"""
  29. def __init__(self):
  30. """初始化策略"""
  31. self.state = StrategyState.WAITING_INIT
  32. self.current_position = None # 当前持仓信息
  33. self.entry_price_bps = 5 # 入场时的价差
  34. self.target_symbol = "DOGE" # 目标交易对
  35. self.account_info = None # 存储账户信息
  36. self.account_index = 318163
  37. self.api_key_index = 0
  38. self.api_client = lighter.ApiClient()
  39. self.account_api = lighter.AccountApi(self.api_client)
  40. self.transaction_api = lighter.TransactionApi(self.api_client)
  41. self.signer_client = lighter.SignerClient(
  42. url='https://mainnet.zklighter.elliot.ai',
  43. private_key='72aafa0426f7ff2806c68625ca5c88de153e34fcb23567f3b872cd56334d2848fb223466efff9c21',
  44. account_index=self.account_index,
  45. api_key_index=self.api_key_index
  46. )
  47. # Check client connection
  48. err = self.signer_client.check_client()
  49. if err is not None:
  50. logger.error(f"SignerClient CheckClient error: {err}")
  51. return
  52. logger.info("策略初始化完成,当前状态: WAITING_INIT")
  53. async def do_strategy(self, market_data):
  54. """
  55. 执行策略逻辑
  56. Args:
  57. market_data: 包含市场数据的字典,格式:
  58. {
  59. 'symbol': str,
  60. 'binance_mark_price': float,
  61. 'binance_price': float,
  62. 'lighter_mark_price': float,
  63. 'lighter_price': float,
  64. 'timestamp': int
  65. }
  66. """
  67. if not market_data:
  68. return
  69. # 每次执行时更新账户信息
  70. try:
  71. account_response = await self.account_api.account(by="index", value=f"{self.account_index}")
  72. if account_response.code == 200:
  73. self.account_info = account_response
  74. # logger.info(f"账户信息更新成功: 可用余额={account_response.accounts[0].available_balance}, 总资产={account_response.accounts[0].total_asset_value}")
  75. else:
  76. logger.warning(f"账户信息查询失败: code={account_response.code}, message={account_response.message}")
  77. except Exception as e:
  78. logger.error(f"查询账户信息时出错: {str(e)}")
  79. return
  80. symbol = market_data.get('symbol')
  81. # 如果是DOGE交易对,打印实时行情
  82. if symbol == self.target_symbol:
  83. await self._print_market_data(market_data)
  84. # 根据当前状态执行相应逻辑
  85. if self.state == StrategyState.WAITING_INIT:
  86. await self._handle_waiting_init()
  87. elif self.state == StrategyState.IDLE_MONITORING:
  88. await self._handle_idle_monitoring(market_data)
  89. elif self.state == StrategyState.EXECUTING_TRADE:
  90. await self._handle_executing_trade(market_data)
  91. elif self.state == StrategyState.WAITING_CONVERGENCE:
  92. await self._handle_waiting_convergence(market_data)
  93. elif self.state == StrategyState.CLOSING_POSITION:
  94. await self._handle_closing_position(market_data)
  95. elif self.state == StrategyState.POSITION_CLOSED:
  96. await self._handle_position_closed()
  97. async def _print_market_data(self, market_data):
  98. """打印市场数据"""
  99. symbol = market_data.get('symbol')
  100. # binance_mark = market_data.get('binance_mark_price')
  101. binance_price = market_data.get('binance_price')
  102. # lighter_mark = market_data.get('lighter_mark_price')
  103. lighter_price = market_data.get('lighter_price')
  104. # 计算价差,转换为bps单位
  105. if binance_price and lighter_price:
  106. # 确保两个价格都是浮点数
  107. binance_price_float = float(binance_price) if isinstance(binance_price, str) else binance_price
  108. lighter_price_float = float(lighter_price) if isinstance(lighter_price, str) else lighter_price
  109. # 计算价差并转换为bps (1bps = 0.01%)
  110. price_diff_bps = int((lighter_price_float - binance_price_float) / binance_price_float * 10000) if binance_price_float else 0
  111. else:
  112. price_diff_bps = None
  113. # 格式化输出
  114. price_diff_str = f"{price_diff_bps}bps" if price_diff_bps is not None else "N/A"
  115. logger.info(f"[{symbol}] Binance: 最新价={binance_price} | Lighter: 最新价={lighter_price} | 价差={price_diff_str}")
  116. async def _handle_waiting_init(self):
  117. """处理等待初始化状态"""
  118. # 初始化完成后转到空闲监听状态
  119. self.state = StrategyState.IDLE_MONITORING
  120. logger.info("状态转换: WAITING_INIT -> IDLE_MONITORING")
  121. async def _handle_idle_monitoring(self, market_data):
  122. """处理空闲监听状态 - 监控价差"""
  123. # TODO: 实现价差监控逻辑
  124. pass
  125. async def _handle_executing_trade(self, market_data):
  126. """处理执行交易状态"""
  127. # TODO: 实现交易执行逻辑
  128. pass
  129. async def _handle_waiting_convergence(self, market_data):
  130. """处理等待收敛状态"""
  131. # TODO: 实现等待价差收敛逻辑
  132. pass
  133. async def _handle_closing_position(self, market_data):
  134. """处理平仓状态"""
  135. # TODO: 实现平仓逻辑
  136. pass
  137. async def _handle_position_closed(self):
  138. """处理平仓完成状态"""
  139. # 平仓完成后回到空闲监听状态
  140. self.state = StrategyState.IDLE_MONITORING
  141. logger.info("状态转换: POSITION_CLOSED -> IDLE_MONITORING")
  142. async def main():
  143. strategy = TradingStrategy()
  144. account = await strategy.account_api.account(by="index", value=f"{strategy.account_index}")
  145. # [AccountPosition(market_id=3, symbol='DOGE', initial_margin_fraction='10.00', open_order_count=0, pending_order_count=0, position_tied_order_count=0, sign=1, position='1', avg_entry_price='0.194368', position_value='0.194360', unrealized_pnl='-0.000008', realized_pnl='0.000000', liquidation_price='0', total_funding_paid_out=None, margin_mode=0, allocated_margin='0.000000', additional_properties={})]
  146. print(account.accounts[0].positions)
  147. doge_market = {
  148. "symbol": "DOGE",
  149. "market_id": 3,
  150. "status": "active",
  151. "taker_fee": "0.0000",
  152. "maker_fee": "0.0000",
  153. "liquidation_fee": "1.0000",
  154. "min_base_amount": "10",
  155. "min_quote_amount": "10.000000",
  156. "order_quote_limit": "",
  157. "supported_size_decimals": 0,
  158. "supported_price_decimals": 6,
  159. "supported_quote_decimals": 6
  160. }
  161. next_nonce = await strategy.transaction_api.next_nonce(account_index=strategy.account_index, api_key_index=strategy.api_key_index)
  162. nonce_value = next_nonce.nonce
  163. base_amount = int(1 * (10 ** doge_market['supported_size_decimals']))
  164. avg_execution_price = int(0.190000 * (10 ** doge_market['supported_price_decimals']))
  165. # 打印所有参数
  166. client_order_index = int(time.time() * 1000)
  167. print("=== 创建订单参数 ===")
  168. print(f"market_index: {doge_market['market_id']}")
  169. print(f"client_order_index: {client_order_index}")
  170. print(f"base_amount: {base_amount}")
  171. print(f"price: {avg_execution_price}")
  172. print(f"is_ask: True")
  173. print(f"order_type: {strategy.signer_client.ORDER_TYPE_MARKET}")
  174. print(f"time_in_force: {strategy.signer_client.ORDER_TIME_IN_FORCE_IMMEDIATE_OR_CANCEL}")
  175. print(f"reduce_only: True")
  176. print(f"trigger_price: 0")
  177. print(f"nonce: {nonce_value}")
  178. print(f"order_expiry: 0")
  179. print("==================")
  180. tx_info, error = strategy.signer_client.sign_create_order(
  181. market_index=doge_market["market_id"],
  182. client_order_index=client_order_index,
  183. base_amount=base_amount,
  184. price=avg_execution_price,
  185. is_ask=True,
  186. order_type=strategy.signer_client.ORDER_TYPE_MARKET,
  187. time_in_force=strategy.signer_client.ORDER_TIME_IN_FORCE_IMMEDIATE_OR_CANCEL,
  188. reduce_only=True,
  189. trigger_price=0,
  190. nonce=nonce_value,
  191. order_expiry=0, # 所有市价单(包括减仓市价单)都必须使用NilOrderExpiry (0)
  192. )
  193. if error is not None:
  194. print(f"Error signing first order (first batch): {error}")
  195. return
  196. print(tx_info)
  197. tx_hash = await strategy.transaction_api.send_tx(strategy.signer_client.TX_TYPE_CREATE_ORDER, tx_info)
  198. print(tx_hash)
  199. if __name__ == '__main__':
  200. import asyncio
  201. asyncio.run(main())