fluent_account_injection.ts 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. #!/usr/bin/env tsx
  2. /**
  3. * 流畅式账户注入 API
  4. * 提供最优雅和直观的账户配置和管理体验
  5. */
  6. import { EventEmitter } from 'events'
  7. // 流畅式账户构建器
  8. class FluentAccountBuilder {
  9. private config: any = {}
  10. static for(exchange: string): FluentAccountBuilder {
  11. const builder = new FluentAccountBuilder()
  12. builder.config.exchange = exchange
  13. return builder
  14. }
  15. account(id: string): this {
  16. this.config.accountId = id
  17. return this
  18. }
  19. alias(name: string): this {
  20. this.config.alias = name
  21. return this
  22. }
  23. priority(level: number): this {
  24. this.config.priority = level
  25. return this
  26. }
  27. withTrading(enabled: boolean = true): this {
  28. this.config.tradingEnabled = enabled
  29. return this
  30. }
  31. withHedging(enabled: boolean = true): this {
  32. this.config.hedgingEnabled = enabled
  33. return this
  34. }
  35. maxPosition(usd: number): this {
  36. this.config.maxPositionUsd = usd
  37. return this
  38. }
  39. maxDailyVolume(usd: number): this {
  40. this.config.maxDailyVolumeUsd = usd
  41. return this
  42. }
  43. withCredentials(creds: Record<string, string>): this {
  44. this.config.credentials = creds
  45. return this
  46. }
  47. fromEnv(envMapping: Record<string, string>): this {
  48. this.config.envMapping = envMapping
  49. return this
  50. }
  51. withRisk(limits: { maxDrawdown?: number; maxLosses?: number }): this {
  52. this.config.riskLimits = limits
  53. return this
  54. }
  55. tagged(...tags: string[]): this {
  56. this.config.tags = tags
  57. return this
  58. }
  59. build(): any {
  60. return {
  61. name: this.config.alias || `${this.config.exchange}-${this.config.accountId}`,
  62. exchange: this.config.exchange,
  63. accountId: this.config.accountId || 'default',
  64. alias: this.config.alias,
  65. enabled: true,
  66. priority: this.config.priority || 1,
  67. tradingEnabled: this.config.tradingEnabled !== false,
  68. hedgingEnabled: this.config.hedgingEnabled !== false,
  69. maxPositionUsd: this.config.maxPositionUsd || 1000,
  70. maxDailyVolumeUsd: this.config.maxDailyVolumeUsd || 10000,
  71. credentials: this.config.credentials,
  72. envMapping: this.config.envMapping,
  73. riskLimits: this.config.riskLimits || {},
  74. tags: this.config.tags || [],
  75. }
  76. }
  77. }
  78. // 流畅式账户管理器
  79. class FluentAccountManager extends EventEmitter {
  80. private accounts: Map<string, any> = new Map()
  81. private hedgeGroups: any[] = []
  82. // 添加单个账户
  83. add(builderFn: (builder: typeof FluentAccountBuilder) => FluentAccountBuilder): this {
  84. const account = builderFn(FluentAccountBuilder).build()
  85. this.accounts.set(account.name, account)
  86. this.emit('account_added', { account })
  87. return this
  88. }
  89. // 批量添加账户
  90. addAll(...configs: Array<(builder: typeof FluentAccountBuilder) => FluentAccountBuilder>): this {
  91. configs.forEach(configFn => this.add(configFn))
  92. return this
  93. }
  94. // 从环境变量自动发现
  95. discoverFromEnv(): this {
  96. console.log('🔍 从环境变量自动发现账户...')
  97. // Pacifica 账户发现
  98. this.discoverPacificaAccounts()
  99. // Aster 账户发现
  100. this.discoverAsterAccounts()
  101. // Binance 账户发现
  102. this.discoverBinanceAccounts()
  103. this.emit('discovery_completed', { count: this.accounts.size })
  104. return this
  105. }
  106. private discoverPacificaAccounts(): void {
  107. const patterns = [
  108. // 单账户模式
  109. { key: 'PACIFICA_PRIVATE_KEY', account: 'PACIFICA_ACCOUNT', suffix: '' },
  110. // 多账户模式 (1-10)
  111. ...Array.from({ length: 10 }, (_, i) => ({
  112. key: `PACIFICA_PRIVATE_KEY_${i + 1}`,
  113. account: `PACIFICA_ACCOUNT_${i + 1}`,
  114. suffix: `_${i + 1}`,
  115. })),
  116. // 角色模式
  117. ...['MAIN', 'HEDGE', 'BACKUP', 'TEST'].map(role => ({
  118. key: `PACIFICA_PRIVATE_KEY_${role}`,
  119. account: `PACIFICA_ACCOUNT_${role}`,
  120. suffix: `_${role}`,
  121. })),
  122. ]
  123. patterns.forEach(pattern => {
  124. if (process.env[pattern.key] && process.env[pattern.account]) {
  125. const account = FluentAccountBuilder.for('pacifica')
  126. .account(process.env[pattern.account]!)
  127. .alias(`Pacifica${pattern.suffix.replace('_', ' ')}`)
  128. .fromEnv({
  129. privateKey: pattern.key,
  130. accountId: pattern.account,
  131. })
  132. .tagged('auto-discovered', 'pacifica')
  133. .build()
  134. this.accounts.set(account.name, account)
  135. console.log(` ✅ 发现 Pacifica 账户: ${account.name}`)
  136. }
  137. })
  138. }
  139. private discoverAsterAccounts(): void {
  140. const patterns = [
  141. { user: 'ASTER_ORDER_USER', signer: 'ASTER_ORDER_SIGNER', key: 'PRIVATE_KEY', suffix: '' },
  142. ...Array.from({ length: 10 }, (_, i) => ({
  143. user: `ASTER_ORDER_USER_${i + 1}`,
  144. signer: `ASTER_ORDER_SIGNER_${i + 1}`,
  145. key: `ASTER_PRIVATE_KEY_${i + 1}`,
  146. suffix: `_${i + 1}`,
  147. })),
  148. ]
  149. patterns.forEach(pattern => {
  150. if (process.env[pattern.user] && process.env[pattern.signer] && process.env[pattern.key]) {
  151. const account = FluentAccountBuilder.for('aster')
  152. .account(process.env[pattern.user]!)
  153. .alias(`Aster${pattern.suffix.replace('_', ' ')}`)
  154. .fromEnv({
  155. user: pattern.user,
  156. signer: pattern.signer,
  157. privateKey: pattern.key,
  158. })
  159. .tagged('auto-discovered', 'aster')
  160. .build()
  161. this.accounts.set(account.name, account)
  162. console.log(` ✅ 发现 Aster 账户: ${account.name}`)
  163. }
  164. })
  165. }
  166. private discoverBinanceAccounts(): void {
  167. const patterns = [
  168. { key: 'BINANCE_API_KEY', secret: 'BINANCE_SECRET_KEY', suffix: '' },
  169. ...Array.from({ length: 10 }, (_, i) => ({
  170. key: `BINANCE_API_KEY_${i + 1}`,
  171. secret: `BINANCE_SECRET_KEY_${i + 1}`,
  172. suffix: `_${i + 1}`,
  173. })),
  174. ]
  175. patterns.forEach(pattern => {
  176. if (process.env[pattern.key] && process.env[pattern.secret]) {
  177. const account = FluentAccountBuilder.for('binance')
  178. .account('default')
  179. .alias(`Binance${pattern.suffix.replace('_', ' ')}`)
  180. .fromEnv({
  181. apiKey: pattern.key,
  182. apiSecret: pattern.secret,
  183. })
  184. .tagged('auto-discovered', 'binance')
  185. .build()
  186. this.accounts.set(account.name, account)
  187. console.log(` ✅ 发现 Binance 账户: ${account.name}`)
  188. }
  189. })
  190. }
  191. // 创建对冲组
  192. createHedgeGroup(name: string, strategy: string, ...accountNames: string[]): this {
  193. const group = {
  194. name,
  195. strategy,
  196. accounts: accountNames,
  197. enabled: true,
  198. maxExposureUsd: 50000,
  199. rebalanceIntervalMs: 30000,
  200. }
  201. this.hedgeGroups.push(group)
  202. this.emit('hedge_group_created', { group })
  203. return this
  204. }
  205. // 启用/禁用账户
  206. enable(accountName: string): this {
  207. const account = this.accounts.get(accountName)
  208. if (account) {
  209. account.enabled = true
  210. this.emit('account_enabled', { account })
  211. }
  212. return this
  213. }
  214. disable(accountName: string): this {
  215. const account = this.accounts.get(accountName)
  216. if (account) {
  217. account.enabled = false
  218. this.emit('account_disabled', { account })
  219. }
  220. return this
  221. }
  222. // 获取账户列表
  223. getAccounts(): any[] {
  224. return Array.from(this.accounts.values())
  225. }
  226. // 按交易所分组
  227. getByExchange(exchange: string): any[] {
  228. return this.getAccounts().filter(acc => acc.exchange === exchange)
  229. }
  230. // 按标签筛选
  231. getByTag(tag: string): any[] {
  232. return this.getAccounts().filter(acc => acc.tags.includes(tag))
  233. }
  234. // 获取启用的账户
  235. getEnabled(): any[] {
  236. return this.getAccounts().filter(acc => acc.enabled)
  237. }
  238. // 生成配置文件
  239. exportConfig(): any {
  240. return {
  241. accounts: this.getAccounts(),
  242. hedgingGroups: this.hedgeGroups,
  243. metadata: {
  244. generatedAt: new Date().toISOString(),
  245. totalAccounts: this.accounts.size,
  246. enabledAccounts: this.getEnabled().length,
  247. },
  248. }
  249. }
  250. // 显示摘要
  251. summary(): this {
  252. console.log('\n📊 账户管理摘要')
  253. console.log('='.repeat(40))
  254. const accounts = this.getAccounts()
  255. const enabled = this.getEnabled()
  256. console.log(`总账户数: ${accounts.length}`)
  257. console.log(`启用账户: ${enabled.length}`)
  258. console.log(`对冲组数: ${this.hedgeGroups.length}`)
  259. // 按交易所统计
  260. const byExchange = new Map<string, number>()
  261. accounts.forEach(acc => {
  262. byExchange.set(acc.exchange, (byExchange.get(acc.exchange) || 0) + 1)
  263. })
  264. console.log('\n按交易所分布:')
  265. byExchange.forEach((count, exchange) => {
  266. console.log(` ${exchange}: ${count} 个`)
  267. })
  268. return this
  269. }
  270. // 验证配置
  271. validate(): { isValid: boolean; errors: string[]; warnings: string[] } {
  272. const result = { isValid: true, errors: [] as string[], warnings: [] as string[] }
  273. const accounts = this.getAccounts()
  274. if (accounts.length === 0) {
  275. result.errors.push('没有配置任何账户')
  276. }
  277. // 检查重复账户ID
  278. const accountIds = new Set()
  279. accounts.forEach(acc => {
  280. const key = `${acc.exchange}:${acc.accountId}`
  281. if (accountIds.has(key)) {
  282. result.errors.push(`重复的账户: ${key}`)
  283. }
  284. accountIds.add(key)
  285. })
  286. // 检查环境变量
  287. accounts.forEach(acc => {
  288. if (acc.envMapping) {
  289. Object.entries(acc.envMapping).forEach(([field, envVar]) => {
  290. if (!process.env[envVar as string]) {
  291. result.warnings.push(`${acc.name}: 环境变量 ${envVar} 未设置`)
  292. }
  293. })
  294. }
  295. })
  296. result.isValid = result.errors.length === 0
  297. return result
  298. }
  299. }
  300. // 演示函数
  301. async function fluentAccountInjectionDemo() {
  302. console.log('🌟 流畅式账户注入演示')
  303. console.log('='.repeat(50))
  304. try {
  305. // 1. 创建流畅式账户管理器
  306. console.log('\n🏗️ 创建流畅式账户管理器...')
  307. const manager = new FluentAccountManager()
  308. // 设置事件监听
  309. manager.on('account_added', ({ account }) => {
  310. console.log(` ➕ 添加账户: ${account.name}`)
  311. })
  312. manager.on('discovery_completed', ({ count }) => {
  313. console.log(` 🔍 自动发现完成: ${count} 个账户`)
  314. })
  315. // 2. 手动添加一些优雅配置的账户
  316. console.log('\n💫 添加精心配置的账户...')
  317. manager
  318. .add(builder =>
  319. builder
  320. .for('pacifica')
  321. .account('trading-main')
  322. .alias('Pacifica 主交易账户')
  323. .priority(1)
  324. .withTrading()
  325. .withHedging()
  326. .maxPosition(25000)
  327. .maxDailyVolume(250000)
  328. .withRisk({ maxDrawdown: 10, maxLosses: 5 })
  329. .tagged('main', 'high-priority', 'production'),
  330. )
  331. .add(builder =>
  332. builder
  333. .for('aster')
  334. .account('hedge-account')
  335. .alias('Aster 对冲账户')
  336. .priority(2)
  337. .withTrading()
  338. .withHedging()
  339. .maxPosition(20000)
  340. .withRisk({ maxDrawdown: 8 })
  341. .tagged('hedge', 'aster', 'production'),
  342. )
  343. .add(builder =>
  344. builder
  345. .for('binance')
  346. .account('backup-spot')
  347. .alias('Binance 备用现货')
  348. .priority(3)
  349. .withTrading(false) // 只读账户
  350. .withHedging(false)
  351. .maxPosition(5000)
  352. .tagged('backup', 'readonly', 'spot'),
  353. )
  354. // 3. 自动发现环境变量中的账户
  355. console.log('\n🔍 自动发现环境变量账户...')
  356. manager.discoverFromEnv()
  357. // 4. 创建对冲组
  358. console.log('\n🔗 创建对冲组...')
  359. manager
  360. .createHedgeGroup('main-hedge', 'delta-neutral', 'Pacifica 主交易账户', 'Aster 对冲账户')
  361. .createHedgeGroup('cross-dex-arbitrage', 'arbitrage', 'Pacifica 主交易账户', 'Binance 备用现货')
  362. // 5. 显示账户摘要
  363. manager.summary()
  364. // 6. 验证配置
  365. console.log('\n✅ 验证账户配置...')
  366. const validation = manager.validate()
  367. if (validation.isValid) {
  368. console.log('🟢 配置验证通过')
  369. } else {
  370. console.log('🔴 配置验证失败:')
  371. validation.errors.forEach(error => console.log(` ❌ ${error}`))
  372. }
  373. if (validation.warnings.length > 0) {
  374. console.log('⚠️ 警告:')
  375. validation.warnings.forEach(warning => console.log(` ⚠️ ${warning}`))
  376. }
  377. // 7. 展示不同的查询方式
  378. console.log('\n🔎 智能查询演示...')
  379. console.log(`📊 启用账户: ${manager.getEnabled().length} 个`)
  380. console.log(`🏦 Pacifica 账户: ${manager.getByExchange('pacifica').length} 个`)
  381. console.log(`🏷️ 生产标签账户: ${manager.getByTag('production').length} 个`)
  382. console.log(`🔄 对冲账户: ${manager.getByTag('hedge').length} 个`)
  383. // 8. 导出配置
  384. console.log('\n📄 导出最终配置...')
  385. const config = manager.exportConfig()
  386. console.log(`配置已生成:`)
  387. console.log(` 账户数量: ${config.accounts.length}`)
  388. console.log(` 对冲组数: ${config.hedgingGroups.length}`)
  389. console.log(` 生成时间: ${config.metadata.generatedAt}`)
  390. // 9. 展示配置预览
  391. if (process.argv.includes('--preview')) {
  392. console.log('\n📋 配置预览:')
  393. console.log(JSON.stringify(config, null, 2))
  394. }
  395. // 10. 演示动态管理
  396. console.log('\n🎛️ 动态管理演示...')
  397. // 禁用备用账户
  398. manager.disable('Binance 备用现货')
  399. console.log(' 🔴 已禁用 Binance 备用账户')
  400. // 启用账户
  401. manager.enable('Binance 备用现货')
  402. console.log(' 🟢 已启用 Binance 备用账户')
  403. console.log('\n✨ 流畅式账户注入演示完成!')
  404. console.log('\n💡 主要特性:')
  405. console.log(' 🔹 链式 API 设计,语法简洁直观')
  406. console.log(' 🔹 智能环境变量发现,支持多种命名约定')
  407. console.log(' 🔹 类型安全的配置构建')
  408. console.log(' 🔹 事件驱动的状态管理')
  409. console.log(' 🔹 灵活的查询和筛选功能')
  410. console.log(' 🔹 内置验证和风险管理')
  411. console.log(' 🔹 支持标签和分组管理')
  412. } catch (error) {
  413. console.error('❌ 演示失败:', error)
  414. }
  415. }
  416. // 显示 API 使用示例
  417. function showApiExamples() {
  418. console.log('\n💡 流畅式 API 使用示例:')
  419. console.log(`
  420. // 1. 创建单个账户
  421. const manager = new FluentAccountManager()
  422. manager.add(builder => builder
  423. .for('pacifica')
  424. .account('my-account')
  425. .alias('我的 Pacifica 账户')
  426. .priority(1)
  427. .withTrading()
  428. .withHedging()
  429. .maxPosition(10000)
  430. .maxDailyVolume(100000)
  431. .tagged('main', 'production')
  432. )
  433. // 2. 批量添加账户
  434. manager.addAll(
  435. builder => builder.for('pacifica').account('main').tagged('main'),
  436. builder => builder.for('aster').account('hedge').tagged('hedge'),
  437. builder => builder.for('binance').account('spot').withTrading(false)
  438. )
  439. // 3. 自动发现 + 手动配置
  440. manager
  441. .discoverFromEnv() // 自动发现
  442. .add(builder => builder.for('pacifica').account('custom')) // 手动添加
  443. .createHedgeGroup('main-hedge', 'delta-neutral', 'account1', 'account2')
  444. // 4. 查询和管理
  445. const pacificaAccounts = manager.getByExchange('pacifica')
  446. const enabledAccounts = manager.getEnabled()
  447. const productionAccounts = manager.getByTag('production')
  448. // 5. 导出配置
  449. const config = manager.exportConfig()
  450. `)
  451. }
  452. // 运行演示
  453. if (import.meta.url === `file://${process.argv[1]}`) {
  454. if (process.argv.includes('--help') || process.argv.includes('-h')) {
  455. showApiExamples()
  456. } else {
  457. fluentAccountInjectionDemo()
  458. }
  459. }