package com.xcong.excoin.modules.okxApi;
|
|
import com.xcong.excoin.modules.okxApi.wsHandler.handler.MarkPriceOkxChannelHandler;
|
import com.xcong.excoin.modules.okxApi.wsHandler.handler.OrdersOkxChannelHandler;
|
import com.xcong.excoin.modules.okxApi.wsHandler.handler.PositionsOkxChannelHandler;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.stereotype.Component;
|
|
import javax.annotation.PostConstruct;
|
import javax.annotation.PreDestroy;
|
import java.math.BigDecimal;
|
|
/**
|
* OKX 盈利回收策略 — 唯一入口,所有参数集中在此。
|
*
|
* <pre>
|
* ┌─────────────────────────────────────────────────────────────────┐
|
* │ 🔧 全部参数在此修改 │
|
* ├──────────────────┬──────────────────────────────────────────────┤
|
* │ 参数名 │ 值 │ 说明 │
|
* ├──────────────────┼──────────────────────────────────────┼────────┤
|
* │ apiKey │ ac76252d-... │ API密钥 │
|
* │ apiSecret │ A8168543... │ 签名密钥│
|
* │ passphrase │ Aa12345678@ │ 口令密码│
|
* ├──────────────────┼──────────────────────────────────────┼────────┤
|
* │ contract │ BTC-USDT-SWAP │ 交易合约│
|
* │ leverage │ 50 │ 杠杆倍数│
|
* │ baseQuantity │ 10 │ 底仓张数│
|
* ├──────────────────┼──────────────────────────────────────┼────────┤
|
* │ profitTriggerRatio│ 0.5 │ 触发ROI │
|
* │ reinvestRatio │ 0.5 │ 补仓比例│
|
* ├──────────────────┼──────────────────────────────────────┼────────┤
|
* │ maxPositionMult │ 10 (= base×10 = 100张上限) │ 风控1 │
|
* │ maxLoss │ 15 USDT │ 风控2 │
|
* │ equityRestartRatio│ 0.05 (= 5%) │ 风控3 │
|
* ├──────────────────┼──────────────────────────────────────┼────────┤
|
* │ contractMult │ 0.01 (BTC 每张0.01个币) │ 合约乘数│
|
* │ priceScale │ 2 (价格精度0.01) │ 价格精度│
|
* │ pnlPriceMode │ LAST_PRICE │ 盈亏计价│
|
* │ isProduction │ false (false=模拟盘) │ 交易环境│
|
* └──────────────────┴──────────────────────────────────────────────┘
|
* </pre>
|
*
|
* <h3>策略核心公式</h3>
|
* <ul>
|
* <li>保证金 = 张数 × 合约乘数 × 开仓均价 / 杠杆</li>
|
* <li>ROI = 未实现盈亏 / 该方向保证金</li>
|
* <li>触发条件:ROI ≥ profitTriggerRatio</li>
|
* <li>平仓:floor(盈利仓位张数 / 2)</li>
|
* <li>补仓保证金 B = 已实现利润 × reinvestRatio</li>
|
* <li>单张保证金 = 合约乘数 × 开仓均价 / 杠杆</li>
|
* <li>补仓张数 = max(baseQuantity, floor(B / 单张保证金))</li>
|
* </ul>
|
*
|
* <h3>仓位演化示例 (BTC-USDT-SWAP, 50x, base10)</h3>
|
* <pre>
|
* 初始: LONG=10 SHORT=10
|
* 多盈: LONG=5 SHORT=12
|
* 多盈: LONG=3 SHORT=15
|
* 多盈: LONG=2 SHORT=18
|
* → 权益达+5% → 全平重置 → LONG=10 SHORT=10
|
* </pre>
|
*
|
* @author Administrator
|
*/
|
@Slf4j
|
@Component
|
public class OkxWebSocketClientManager {
|
|
// ╔══════════════════════════════════════════════════════════════╗
|
// ║ 🔐 OKX API 认证信息 ║
|
// ╚══════════════════════════════════════════════════════════════╝
|
private static final String OKX_API_KEY = "ac76252d-e717-4459-a6f9-80512aed5ea0";
|
private static final String OKX_API_SECRET = "A8168543EF4F08A6DBFE27AB23956898";
|
private static final String OKX_PASSPHRASE = "Aa12345678@";
|
|
// ╔══════════════════════════════════════════════════════════════╗
|
// ║ 📊 交易标的参数 ║
|
// ╚══════════════════════════════════════════════════════════════╝
|
private static final String CONTRACT = "BTC-USDT-SWAP"; // 合约名称
|
private static final String LEVERAGE = "50"; // 杠杆倍数
|
private static final String MARGIN_MODE = "cross"; // 全仓 cross / 逐仓 isolated
|
private static final String POSITION_MODE = "long_short_mode"; // 双向持仓
|
|
// ╔══════════════════════════════════════════════════════════════╗
|
// ║ 🎯 策略核心参数 ║
|
// ╚══════════════════════════════════════════════════════════════╝
|
/** 基础仓位张数 — 初始化时多空各开此张数,也是最小开仓单位 */
|
private static final String BASE_QUANTITY = "10";
|
/** 盈利触发比例 — ROI=未实现盈亏/保证金 达到此值时触发平仓 */
|
private static final BigDecimal PROFIT_TRIGGER_RATIO = new BigDecimal("0.5"); // 50%
|
/** 再投资比例 — 已实现利润中用于补反向仓的比例 */
|
private static final BigDecimal REINVEST_RATIO = new BigDecimal("0.5"); // 50%
|
|
// ╔══════════════════════════════════════════════════════════════╗
|
// ║ 🛡 风控参数 ║
|
// ╚══════════════════════════════════════════════════════════════╝
|
/** 风控1: 反向仓位倍数上限 — 反向最大持仓 = baseQuantity × 此值 (10×10=100张) */
|
private static final int MAX_POSITION_MULTIPLIER = 10;
|
/** 风控2: 最大亏损阈值(USDT) — 全局盈亏≤-此值时停止策略 */
|
private static final BigDecimal MAX_LOSS = new BigDecimal("15");
|
/** 风控3: 权益重置比例 — 账户权益 ≥ 初始权益 × (1+此值) 时全平重新双开 */
|
private static final BigDecimal EQUITY_RESTART_RATIO = new BigDecimal("0.05"); // 5%
|
|
// ╔══════════════════════════════════════════════════════════════╗
|
// ║ ⚙ 技术与环境参数 ║
|
// ╚══════════════════════════════════════════════════════════════╝
|
/** 合约乘数 — BTC-USDT-SWAP 每张=0.01 BTC */
|
private static final BigDecimal CONTRACT_MULTIPLIER = new BigDecimal("0.01");
|
/** 价格精度 — OKX 价格小数位数 (BTC=2, ETH=2) */
|
private static final int PRICE_SCALE = 2;
|
/** 盈亏计价模式 — LAST_PRICE(最新价) / MARK_PRICE(标记价) */
|
private static final OkxConfig.PnLPriceMode PNL_PRICE_MODE = OkxConfig.PnLPriceMode.LAST_PRICE;
|
/** false=模拟盘 (wspap.okx.com) / true=实盘 (ws.okx.com) */
|
private static final boolean IS_PRODUCTION = false;
|
|
// ==================== 以下为启动代码,通常无需修改 ====================
|
|
private OkxKlineWebSocketClient wsClient;
|
private OkxProfitRecycleStrategy strategy;
|
private OkxConfig config;
|
|
@PostConstruct
|
public void init() {
|
log.info("[OKX] 正在初始化盈利回收策略...");
|
|
try {
|
config = OkxConfig.builder()
|
.apiKey(OKX_API_KEY)
|
.apiSecret(OKX_API_SECRET)
|
.passphrase(OKX_PASSPHRASE)
|
.contract(CONTRACT)
|
.leverage(LEVERAGE)
|
.marginMode(MARGIN_MODE)
|
.positionMode(POSITION_MODE)
|
.baseQuantity(BASE_QUANTITY)
|
.maxLoss(MAX_LOSS)
|
.priceScale(PRICE_SCALE)
|
.contractMultiplier(CONTRACT_MULTIPLIER)
|
.unrealizedPnlPriceMode(PNL_PRICE_MODE)
|
.isProduction(IS_PRODUCTION)
|
.profitTriggerRatio(PROFIT_TRIGGER_RATIO)
|
.reinvestRatio(REINVEST_RATIO)
|
.maxPositionMultiplier(MAX_POSITION_MULTIPLIER)
|
.equityRestartRatio(EQUITY_RESTART_RATIO)
|
.build();
|
|
strategy = new OkxProfitRecycleStrategy(config);
|
strategy.init();
|
|
wsClient = new OkxKlineWebSocketClient(config);
|
wsClient.addPublicHandler(new MarkPriceOkxChannelHandler(config.getContract(), strategy));
|
wsClient.addPrivateHandler(new PositionsOkxChannelHandler(config, strategy));
|
wsClient.addPrivateHandler(new OrdersOkxChannelHandler(config, strategy));
|
|
strategy.setWsClient(wsClient);
|
wsClient.init();
|
log.info("[OKX] WS已连接 | 合约: {} | 杠杆: {}x | 基础张数: {} | "
|
+ "触发ROI: {}% | 补仓比例: {}% | 仓位上限: {}x | 重置阈值: {}%",
|
CONTRACT, LEVERAGE, BASE_QUANTITY,
|
PROFIT_TRIGGER_RATIO.multiply(new BigDecimal("100")),
|
REINVEST_RATIO.multiply(new BigDecimal("100")),
|
MAX_POSITION_MULTIPLIER,
|
EQUITY_RESTART_RATIO.multiply(new BigDecimal("100")));
|
|
strategy.startStrategy();
|
} catch (Exception e) {
|
log.error("[OKX] 初始化失败", e);
|
}
|
}
|
|
@PreDestroy
|
public void destroy() {
|
log.info("[OKX] 正在销毁...");
|
if (strategy != null) strategy.stopStrategy();
|
if (wsClient != null) wsClient.destroy();
|
log.info("[OKX] 销毁完成");
|
}
|
|
public OkxKlineWebSocketClient getKlineWebSocketClient() { return wsClient; }
|
public OkxProfitRecycleStrategy getStrategy() { return strategy; }
|
public IOkxStrategy getActiveStrategy() { return strategy; }
|
}
|