
이 전략의 영감은 지후 작가의 “드림 딜러” 기회 게시물인 “트럼프와 멜라니아 저위험 상관관계 차익거래 모델”에서 나왔습니다. 이 기사에서는 BN(TRUMP와 MELANIA)에서 출시된 두 계약 간의 가격 상관관계를 살펴보고, 두 계약 간의 미묘한 시간 지연을 활용하여 단기 시장 변동을 포착하고 저위험 차익거래를 달성하고자 합니다. 다음으로, 이 전략의 원칙과 코드 구현 논리를 설명하고 가능한 최적화 방향을 살펴보겠습니다.
미리 가야해요알아채다문제는 이 전략이 수동 거래 작업과 동일하다는 것입니다. 두 개의 적합한 거래 쌍을 찾은 후에야 일정한 수익 기회가 생기고 거래 쌍의 수익 수명은 짧을 수 있습니다. 수익 기회가 없다는 것을 발견하면 수익 하락이나 손실을 방지하기 위해 제때 전략을 중단해야 합니다.
TRUMP와 MELANIA 계약은 모두 동일한 발행팀에서 발행하고 동일한 통제 기금을 갖고 있으므로 가격 추세는 대부분 매우 동기화되어 있습니다. 하지만 계약 설계나 시장 실행 등의 요소로 인해 MELANIA의 가격은 TRUMP보다 1~2초 정도 뒤떨어지는 경향이 있습니다. 이러한 작은 지연은 중재자에게 가격 차이를 포착하고 고빈도 복제 거래를 수행할 수 있는 기회를 제공합니다. 간단히 말해서, TRUMP가 급격하게 변동할 때, MELANIA는 바로 그 뒤를 따르는 경향이 있습니다. 이 지연을 이용하면 더 낮은 위험으로 거래를 완료할 수 있습니다.


유사한 상관관계 현상은 암호화폐 시장에서는 드문 일이 아닙니다.
이러한 상관관계는 고빈도 트레이더와 차익거래자에게 안정적인 거래 신호와 위험이 낮은 운영 기회를 제공하지만, 동시에 미묘한 시장 변화에도 매우 민감하게 반응하고 실시간으로 대응할 수 있는 거래 전략이 필요합니다.
코드는 주로 여러 부분으로 구성되며, 각 모듈은 중재 전략의 주요 단계에 해당합니다.
function GetPosition(pair){
let pos = exchange.GetPosition(pair)
if(pos.length == 0){
return {amount:0, price:0, profit:0}
}else if(pos.length > 1){
throw '不支持双向持仓'
}else if(pos.length == 1){
return {amount:pos[0].Type == 0 ? pos[0].Amount : -pos[0].Amount, price:pos[0].Price, profit:pos[0].Profit}
}else{
Log('未获取仓位数据')
return null
}
}
function InitAccount(){
let account = _C(exchange.GetAccount)
let total_eq = account.Equity
let init_eq = 0
if(!_G('init_eq')){
init_eq = total_eq
_G('init_eq', total_eq)
}else{
init_eq = _G('init_eq')
}
return init_eq
}
function CancelPendingOrders() {
orders = exchange.GetOrders(); // 获取订单
for (let order of orders) {
if (order.Status == ORDER_STATE_PENDING) { // 只取消未完成的订单
exchange.CancelOrder(order.Id); // 取消挂单
}
}
}
주요 함수는 무한 루프를 사용하여 다음 단계를 지속적으로 실행합니다.
데이터 수집 및 시장 계산
각 사이클은 다음으로 시작됩니다.exchange.GetRecords Pair_A와 Pair_B의 시장 데이터를 각각 가져옵니다.
개장조건을 확인하여 주문하기
현재 포지션이 없고(position_B.amount == 0) 거래가 허용되는 경우(afterTrade==1):
손절매와 손절매 논리
포지션이 확립되면 전략은 포지션 방향에 따라 해당 이익 실현 주문과 손절매 주문을 설정합니다.
포지션 마감 후 수익 통계 및 로그 기록
각 포지션이 마감된 후, 시스템은 계정 자본의 변화를 얻고 수익 횟수, 손실 횟수, 누적 수익/손실 금액을 계산합니다.
동시에 표와 그래프를 사용하여 현재 위치 정보, 거래 통계 및 사이클 지연을 실시간으로 표시하므로 후속 전략 효과 분석에 편리합니다.
이 전략은 두 개의 높은 상관관계를 가진 계약 간의 미묘한 지연을 활용하지만 여전히 개선할 수 있는 영역이 많이 있습니다.
이 글에서는 단기지연계약상관관계차익거래 전략의 기본 원칙과 구현 코드를 자세히 소개합니다. 가격 상승과 하락의 차이를 이용하는 것부터 진입 기회를 포착하는 것, 포지션 관리를 위한 손절매와 손절매를 설정하는 것까지, 이 전략은 암호화폐 시장의 자산 간의 높은 상관관계를 최대한 활용합니다. 동시에 우리는 전략의 안정성과 수익성을 실시간 애플리케이션에서 더욱 개선하기 위해 동적 매개변수 조정, 신호 필터링, 시스템 견고성 및 코드 최적화를 포함한 여러 가지 최적화 제안을 제시했습니다.
이 전략은 독특한 영감을 받았고 구현하기도 간단하지만, 빈도가 높고 변동성이 큰 암호화폐 시장에서는 모든 차익거래를 신중하게 처리해야 합니다. 이 글이 양적 거래와 차익거래 전략에 관심이 있는 친구들에게 귀중한 참고 자료와 영감을 제공하기를 바랍니다.
참고: 전략 테스트 환경은 OKX 시뮬레이션 거래이며, 구체적인 세부 사항은 다른 거래소에 따라 수정될 수 있습니다.
function GetPosition(pair){
let pos = exchange.GetPosition(pair)
if(pos.length == 0){
return {amount:0, price:0, profit:0}
}else if(pos.length > 1){
throw '不支持双向持仓'
}else if(pos.length == 1){
return {amount:pos[0].Type == 0 ? pos[0].Amount : -pos[0].Amount, price:pos[0].Price, profit:pos[0].Profit}
}else{
Log('未获取仓位数据')
return null
}
}
function InitAccount(){
let account = _C(exchange.GetAccount)
let total_eq = account.Equity
let init_eq = 0
if(!_G('init_eq')){
init_eq = total_eq
_G('init_eq', total_eq)
}else{
init_eq = _G('init_eq')
}
return init_eq
}
function CancelPendingOrders() {
orders = exchange.GetOrders(); // 获取订单
for (let order of orders) {
if (order.Status == ORDER_STATE_PENDING) { // 只取消未完成的订单
exchange.CancelOrder(order.Id); // 取消挂单
}
}
}
var pair_a = Pair_A + "_USDT.swap";
var pair_b = Pair_B + "_USDT.swap";
function main() {
exchange.IO('simulate', true);
LogReset(0);
Log('策略开始运行')
var precision = exchange.GetMarkets();
var ratio = 0
var takeProfitOrderId = null;
var stopLossOrderId = null;
var successCount = 0;
var lossCount = 0;
var winMoney = 0;
var failMoney = 0;
var afterTrade = 1;
var initEq = InitAccount();
var curEq = initEq
var pricePrecision = precision[pair_b].PricePrecision;
while (true) {
try{
let startLoopTime = Date.now();
let position_B = GetPosition(pair_b);
let new_r_pairB = exchange.GetRecords(pair_b, 1).slice(-1)[0];
if (!new_r_pairB || !position_B) {
Log('跳过当前循环');
continue;
}
// 合并交易条件:检查是否可以开仓并进行交易
if (afterTrade == 1 && position_B.amount == 0) {
let new_r_pairA = exchange.GetRecords(pair_a, 1).slice(-1)[0];
if (!new_r_pairA ) {
Log('跳过当前循环');
continue;
}
ratio = (new_r_pairA.Close - new_r_pairA.Open) / new_r_pairA.Open - (new_r_pairB.Close - new_r_pairB.Open) / new_r_pairB.Open;
if (ratio > diffLevel) {
CancelPendingOrders();
Log('实时ratio:', ratio, '买入:', pair_b, position_B.amount);
exchange.CreateOrder(pair_b, "buy", -1, Trade_Number);
afterTrade = 0;
} else if (ratio < -diffLevel) {
CancelPendingOrders();
Log('实时ratio:', ratio, '卖出:', pair_b, position_B.amount);
exchange.CreateOrder(pair_b, "sell", -1, Trade_Number);
afterTrade = 0;
}
}
// 判断止盈止损
if (position_B.amount > 0 && takeProfitOrderId == null && stopLossOrderId == null && afterTrade == 0) {
Log('多仓持仓价格:', position_B.price, '止盈价格:', position_B.price * (1 + stopProfitLevel), '止损价格:', position_B.price * (1 - stopLossLevel));
takeProfitOrderId = exchange.CreateOrder(pair_b, "closebuy", position_B.price * (1 + stopProfitLevel), position_B.amount);
Log('止盈订单:', takeProfitOrderId);
}
if (position_B.amount > 0 && takeProfitOrderId != null && stopLossOrderId == null && new_r_pairB.Close < position_B.price * (1 - stopLossLevel) && afterTrade == 0) {
CancelPendingOrders();
takeProfitOrderId = null
Log('多仓止损');
stopLossOrderId = exchange.CreateOrder(pair_b, "closebuy", -1, position_B.amount);
Log('多仓止损订单:', stopLossOrderId);
}
if (position_B.amount < 0 && takeProfitOrderId == null && stopLossOrderId == null && afterTrade == 0) {
Log('空仓持仓价格:', position_B.price, '止盈价格:', position_B.price * (1 - stopProfitLevel), '止损价格:', position_B.price * (1 + stopLossLevel));
takeProfitOrderId = exchange.CreateOrder(pair_b, "closesell", position_B.price * (1 - stopProfitLevel), -position_B.amount);
Log('止盈订单:', takeProfitOrderId, '当前价格:', new_r_pairB.Close );
}
if (position_B.amount < 0 && takeProfitOrderId != null && stopLossOrderId == null && new_r_pairB.Close > position_B.price * (1 + stopLossLevel) && afterTrade == 0) {
CancelPendingOrders();
takeProfitOrderId = null
Log('空仓止损');
stopLossOrderId = exchange.CreateOrder(pair_b, "closesell", -1, -position_B.amount);
Log('空仓止损订单:', stopLossOrderId);
}
// 平市价单未完成
if (takeProfitOrderId == null && stopLossOrderId != null && afterTrade == 0) {
let stoplosspos = GetPosition(pair_b)
if(stoplosspos.amount > 0){
Log('平多仓市价单未完成')
exchange.CreateOrder(pair_b, 'closebuy', -1, stoplosspos.amount)
}
if(stoplosspos.amount < 0){
Log('平空仓市价单未完成')
exchange.CreateOrder(pair_b, 'closesell', -1, -stoplosspos.amount)
}
}
// 未平仓完毕
if (Math.abs(position_B.amount) < Trade_Number && Math.abs(position_B.amount) > 0 && afterTrade == 0){
Log('未平仓完毕')
if(position_B.amount > 0){
exchange.CreateOrder(pair_b, 'closebuy', -1, position_B.amount)
}else{
exchange.CreateOrder(pair_b, 'closesell', -1, -position_B.amount)
}
}
// 计算盈亏
if (position_B.amount == 0 && afterTrade == 0) {
if (stopLossOrderId != null || takeProfitOrderId != null) {
stopLossOrderId = null;
takeProfitOrderId = null;
let afterEquity = exchange.GetAccount().Equity;
let curAmount = afterEquity - curEq;
curEq = afterEquity
if (curAmount > 0) {
successCount += 1;
winMoney += curAmount;
Log('盈利金额:', curAmount);
} else {
lossCount += 1;
failMoney += curAmount;
Log('亏损金额:', curAmount);
}
afterTrade = 1;
}
}
if (startLoopTime % 10 == 0) { // 每 10 次循环记录一次
let curEquity = exchange.GetAccount().Equity
// 输出交易信息表
let table = {
type: "table",
title: "交易信息",
cols: [
"初始权益", "当前权益", Pair_B + "仓位", Pair_B + "持仓价", Pair_B + "收益", Pair_B + "价格",
"盈利次数", "盈利金额", "亏损次数", "亏损金额", "胜率", "盈亏比"
],
rows: [
[
_N(_G('init_eq'), 2), // 初始权益
_N(curEquity, 2), // 当前权益
_N(position_B.amount, 1), // Pair B 仓位
_N(position_B.price, pricePrecision), // Pair B 持仓价
_N(position_B.profit, 1), // Pair B 收益
_N(new_r_pairB.Close, pricePrecision), // Pair B 价格
_N(successCount, 0), // 盈利次数
_N(winMoney, 2), // 盈利金额
_N(lossCount, 0), // 亏损次数
_N(failMoney, 2), // 亏损金额
_N(successCount + lossCount === 0 ? 0 : successCount / (successCount + lossCount), 2), // 胜率
_N(failMoney === 0 ? 0 : winMoney / failMoney * -1, 2) // 盈亏比
]
]
};
$.PlotMultLine("ratio plot", "幅度变化差值", ratio, startLoopTime);
$.PlotMultHLine("ratio plot", diffLevel, "差价上限", "red", "ShortDot");
$.PlotMultHLine("ratio plot", -diffLevel, "差价下限", "blue", "ShortDot");
LogStatus("`" + JSON.stringify(table) + "`");
LogProfit(curEquity - initEq, '&')
}
}catch(e){
Log('策略出现错误:', e)
}
Sleep(200);
}
}