
최근 FMZ 공식 그룹에서 마팅게일 전략에 대한 논의가 많이 이뤄지고 있지만, 플랫폼에는 디지털 통화 계약에 대한 마팅게일 전략이 많지 않습니다. 그래서 저는 이 기회를 빌려 암호화폐 선물을 위한 간단한 마팅게일 전략을 설계했습니다. 왜 마틴과 같은 전략이라고 불리는가? 마틴 전략의 잠재적인 위험은 실제로 작지 않기 때문에 마틴 전략에 따라 완전히 설계되지 않았기 때문입니다. 하지만 이러한 유형의 전략은 여전히 상당한 리스크를 가지고 있으며, 마팅게일 전략의 매개변수 설정은 리스크와 밀접한 관련이 있으며, 리스크를 무시해서는 안 됩니다.
이 글은 주로 마틴 유형 전략의 설계를 설명하고 연구합니다. 전략 아이디어 자체는 매우 명확합니다. FMZ 사용자로서 우리는 전략 설계를 더 많이 고려합니다.
디지털 통화 선물 전략을 설계할 때, 전체 주식 데이터가 자주 사용됩니다. 특히 변동 수익률을 계산해야 할 때 수익률을 계산하는 것이 필요하기 때문입니다. 미결제 포지션은 증거금을 차지하므로, 보류 주문도 증거금을 차지합니다. 이때 FMZ 플랫폼의 API 인터페이스를 호출합니다.exchange.GetAccount()획득되는 것은 사용 가능한 자산과 보류 중인 주문에 의해 동결된 자산입니다. 실제로 대부분의 디지털 통화 선물 거래소는 총 자본에 대한 데이터를 제공하지만 FMZ는 이 속성을 균일하게 포괄하지 않습니다.
따라서 우리는 다양한 거래소에 따라 이 데이터를 얻기 위한 함수를 설계합니다.
// OKEX V5 获取总权益
function getTotalEquity_OKEX_V5() {
var totalEquity = null
var ret = exchange.IO("api", "GET", "/api/v5/account/balance", "ccy=USDT")
if (ret) {
try {
totalEquity = parseFloat(ret.data[0].details[0].eq)
} catch(e) {
Log("获取账户总权益失败!")
return null
}
}
return totalEquity
}
// 币安期货
function getTotalEquity_Binance() {
var totalEquity = null
var ret = exchange.GetAccount()
if (ret) {
try {
totalEquity = parseFloat(ret.Info.totalWalletBalance)
} catch(e) {
Log("获取账户总权益失败!")
return null
}
}
return totalEquity
}
코드에서totalEquity이것이 우리에게 필요한 총 자본입니다. 그런 다음 호출 항목으로 함수를 작성하고 거래소 이름에 따라 해당 함수를 호출합니다.
function getTotalEquity() {
var exName = exchange.GetName()
if (exName == "Futures_OKCoin") {
return getTotalEquity_OKEX_V5()
} else if (exName == "Futures_Binance") {
return getTotalEquity_Binance()
} else {
throw "不支持该交易所"
}
}
주요 함수와 주요 논리를 설계하기 전에. 아직 준비해야 할 부분이 있고, 보조 기능을 설계해야 할 부분도 있습니다.
function cancelAll() {
while (1) {
var orders = _C(exchange.GetOrders)
if (orders.length == 0) {
break
}
for (var i = 0 ; i < orders.length ; i++) {
exchange.CancelOrder(orders[i].Id, orders[i])
Sleep(500)
}
Sleep(500)
}
}
FMZ Strategy Square의 전략 예제 코드를 자주 보는 사람들은 이 기능에 매우 익숙할 것이라고 생각합니다. 많은 전략이 비슷한 디자인을 사용했습니다. 이 함수의 기능은 보류 중인 주문의 현재 목록을 얻고 이를 하나씩 취소하는 것입니다.
function trade(distance, price, amount) {
var tradeFunc = null
if (distance == "buy") {
tradeFunc = exchange.Buy
} else if (distance == "sell") {
tradeFunc = exchange.Sell
} else if (distance == "closebuy") {
tradeFunc = exchange.Sell
} else {
tradeFunc = exchange.Buy
}
exchange.SetDirection(distance)
return tradeFunc(price, amount)
}
function openLong(price, amount) {
return trade("buy", price, amount)
}
function openShort(price, amount) {
return trade("sell", price, amount)
}
function coverLong(price, amount) {
return trade("closebuy", price, amount)
}
function coverShort(price, amount) {
return trade("closesell", price, amount)
}
선물 거래에는 4가지 방향이 있습니다. 롱 포지션을 여는 것(openLong), 숏 포지션을 여는 것(openShort), 롱 포지션을 청산하는 것(coverLong), 숏 포지션을 청산하는 것(coverShort). 그래서 우리는 이러한 작업에 대응하기 위해 4개의 주문 함수를 설계했습니다. 주문만 하기로 결정했다면, 몇 가지 필수 요소가 있습니다. 주문 방향, 주문 가격, 주문 수량입니다.
그래서 우리는 다음과 같은 프로그램도 설계했습니다.trade처리할 기능方向(distance)、下单价格(price)、下单量(amount)모든 작업이 완료되었습니다.
롱 포지션 오픈(openLong), 숏 포지션 오픈(openShort), 롱 포지션 클로징(coverLong), 숏 포지션 클로징(coverShort) 함수 호출은 최종적으로 다음과 같이 실행됩니다.trade이 기능은 설정된 방향, 가격, 수량에 따라 선물 거래소에 주문을 내는 실제 기능을 수행합니다.
전략은 매우 간단합니다. 현재 가격을 기준으로 삼고 현재 가격 위아래로 일정 거리만큼 매도 주문(숏)과 매수 주문(롱)을 내는 것입니다. 한쪽이 실행되면 나머지 모든 주문은 취소되고, 포지션 가격을 기준으로 일정 거리에 새로운 마감 주문이 배치되고 업데이트된 현재 가격에 증가 주문이 배치되지만 증가 주문은 주문 수량을 두 배로 늘리지 마세요.
var buyOrderId = null
var sellOrderId = null
그런 다음 OKEX_V5 시뮬레이션 디스크를 사용하는 옵션이 전략 인터페이스 매개변수에 설계되었으므로 코드에서 일부 처리를 수행해야 합니다.
var exName = exchange.GetName()
// 切换OKEX V5模拟盘
if (isSimulate && exName == "Futures_OKCoin") {
exchange.IO("simulate", true)
}
인터페이스 매개변수에는 모든 정보를 재설정하는 옵션도 포함되어 있으므로 코드에도 해당 처리가 있어야 합니다.
if (isReset) {
_G(null)
LogReset(1)
LogProfitReset()
LogVacuum()
Log("重置所有数据", "#FF0000")
}
저희는 영구 계약만 운영하므로 여기에 하드코딩되어 있으며 영구 계약에만 설정되어 있습니다.
exchange.SetContractType("swap")
그러면 주문 가격과 주문 수량의 정확도도 고려해야 합니다. 정확도가 제대로 설정되지 않으면 전략 계산 과정에서 정확도가 손실됩니다. 데이터에 소수점 자릿수가 많으면 주문이 쉽게 교환 인터페이스에서 거부되었습니다.
exchange.SetPrecision(pricePrecision, amountPrecision)
Log("设置精度", pricePrecision, amountPrecision)
간단한 데이터 복구 기능
if (totalEq == -1 && !IsVirtual()) {
var recoverTotalEq = _G("totalEq")
if (!recoverTotalEq) {
var currTotalEq = getTotalEquity()
if (currTotalEq) {
totalEq = currTotalEq
_G("totalEq", currTotalEq)
} else {
throw "获取初始权益失败"
}
} else {
totalEq = recoverTotalEq
}
}
전략 실행 시 초기 총 계정 자본을 지정하려면 매개변수를 설정할 수 있습니다.totalEq이 매개변수를 -1로 설정하면 전략은 저장된 총 자본 데이터를 읽습니다. 저장된 총 자본 데이터가 없으면 현재 읽은 총 자본이 전략 실행 진행의 초기 총 자본으로 사용됩니다. 총 자본이 자본이 증가한다는 것은 돈을 벌었지만 총 자본이 줄었다는 것을 의미합니다. 즉, 돈을 잃었다는 뜻입니다. 총 자본 데이터를 읽으면 이 데이터를 사용하여 계속 실행합니다.
while (1) { // 策略主要逻辑设计为一个死循环
var ticker = _C(exchange.GetTicker) // 首先读取当前行情信息,主要用到最新成交价
var pos = _C(exchange.GetPosition) // 读取当前持仓数据
if (pos.length > 1) { // 判断持仓数据,由于这个策略的逻辑,是不太可能同时出现多空持仓的,所以发现同时出现多空持仓就抛出错误
Log(pos)
throw "同时有多空持仓" // 抛出错误,让策略停止
}
// 根据状态而定
if (pos.length == 0) { // 根据持仓状态做出不同操作,pos.length == 0是当没有持仓时
// 未持仓了,统计一次收益
if (!IsVirtual()) {
var currTotalEq = getTotalEquity()
if (currTotalEq) {
LogProfit(currTotalEq - totalEq, "当前总权益:", currTotalEq)
}
}
buyOrderId = openLong(ticker.Last - targetProfit, amount) // 挂开多仓的买单
sellOrderId = openShort(ticker.Last + targetProfit, amount) // 挂开空仓的卖单
} else if (pos[0].Type == PD_LONG) { // 有多头持仓,挂单位置、数量有所不同
var n = 1
var price = ticker.Last
buyOrderId = openLong(price - targetProfit * n, amount)
sellOrderId = coverLong(pos[0].Price + targetProfit, pos[0].Amount)
} else if (pos[0].Type == PD_SHORT) { // 有空头持仓,挂单位置、数量有所不同
var n = 1
var price = ticker.Last
buyOrderId = coverShort(pos[0].Price - targetProfit, pos[0].Amount)
sellOrderId = openShort(price + targetProfit * n, amount)
}
if (!sellOrderId || !buyOrderId) { // 如果有一边挂单失败就取消所有挂单,重来
cancelAll()
buyOrderId = null
sellOrderId = null
continue
}
while (1) { // 挂单完成,开始监控订单
var isFindBuyId = false
var isFindSellId = false
var orders = _C(exchange.GetOrders)
for (var i = 0 ; i < orders.length ; i++) {
if (buyOrderId == orders[i].Id) {
isFindBuyId = true
}
if (sellOrderId == orders[i].Id) {
isFindSellId = true
}
}
if (!isFindSellId && !isFindBuyId) { // 检测到买卖单都成交了
cancelAll()
break
} else if (!isFindBuyId) { // 检测到买单成交
Log("买单成交")
cancelAll()
break
} else if (!isFindSellId) { // 检测到卖单成交
Log("卖单成交")
cancelAll()
break
}
LogStatus(_D())
Sleep(3000)
}
Sleep(500)
}
전체적인 논리와 설계가 설명되었습니다.
5월 19일의 시장 상황을 전략으로 경험해 보세요.


마팅게일 전략은 여전히 어느 정도의 위험을 갖고 있다는 것을 알 수 있습니다.

전략 주소: https://www.fmz.com/strategy/294957
전략은 주로 학습용으로 사용되므로, 실제 돈을 사용할 때는 주의하시기 바랍니다~!