최근에는 FMZ 공식 그룹에서 많은 마틴게일 전략이 논의되고 있으며, 플랫폼에서 암호화폐 계약의 마틴게일 전략은 많지 않습니다. 따라서, 저는 이 기회를 이용해 암호화폐 선물에 대한 간단한 마틴게일 전략을 설계했습니다. 왜 마틴게일 전략이라고 불리는가? 마틴 전략의 잠재적 위험은 실제로 작지 않기 때문에 마틴 전략에 따라 정확하게 설계되지 않았기 때문입니다. 그러나, 이 유형의 전략은 여전히 많은 위험을 가지고 있으며, 마틴 유형의 전략의 매개 변수 설정은 위험과 밀접하게 관련이 있으며, 위험을 무시해서는 안됩니다.
이 문서에서는 주로 마르틴형 전략의 설계에 대해 설명하고 학습합니다. 전략 아이디어가 매우 명확하기 때문에 FMZ의 사용자로서 전략 설계를 더 고려합니다.
전체 자본은 종종 암호화폐 선물 전략을 설계할 때 사용됩니다. 이것은 수익을 계산해야하기 때문입니다. 특히 부동 수익을 계산해야 할 때입니다. 포지션은 마진으로 점유되어 있기 때문에 미뤄진 주문도 점유됩니다. 이 시점에서 API 인터페이스는exchange.GetAccount()
FMZ 플랫폼의 사용 가능한 자산과 대기 주문 동결 자산을 얻기 위해 호출됩니다. 사실, 대부분의 암호화폐 선물 거래소는 총 자본의 데이터를 제공하지만이 속성은 FMZ에 균일하게 포장되지 않습니다.
그래서 우리는 서로 다른 교환에 따라 이 데이터를 얻기 위해 함수를 설계합니다.
// OKEX V5 obtain total equity
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("failed to obtain the total equity of the account!")
return null
}
}
return totalEquity
}
// Binance futures
function getTotalEquity_Binance() {
var totalEquity = null
var ret = exchange.GetAccount()
if (ret) {
try {
totalEquity = parseFloat(ret.Info.totalWalletBalance)
} catch(e) {
Log("failed to obtain the total equity of the account!")
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 "This exchange is not supported"
}
}
주요 함수와 주요 논리를 설계하기 전에, 우리는 몇 가지 준비를하고 몇 가지 보조 기능을 설계해야합니다.
모든 현재 대기 주문을 취소합니다.
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 전략 사각형의 전략 예제 코드를 자주 읽는 사람들에게 익숙하며, 많은 전략이 유사한 디자인을 사용했습니다. 기능은 현재 미뤄진 주문 목록을 얻고 하나씩 취소하는 것입니다.
미래에 대한 투입
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)
}
선물 거래에는 네 가지 방향이 있습니다: openLong, openShort, coverLong andcoverShort. 그래서 우리는 이러한 작업에 대응하는 네 가지 주문 기능을 설계했습니다. 주문만을 고려하면 방향, 주문 가격 및 주문 양이 몇 가지 필요한 요소가 있습니다.
그래서 우리는 이렇게 하는 함수를 디자인했습니다.trade
작업 처리 할 때distance
, price
, amount
정해져 있습니다.
openLong, openShort, coverLong 및 coverShort에 대한 함수 호출은trade
기능, 즉, 설정된 거리와 가격, 그리고 양에 기초한 선물 거래소에 주문을 하는 것입니다.
전략 아이디어는 매우 간단합니다. 현재 가격을 기준으로 취하고 특정 거리에 판매 (단거리) 및 구매 (장거리) 명령을 올리고 아래로합니다. 거래가 완료되면 나머지 모든 주문이 취소되고 그 다음 포지션 가격에 따라 특정 거리에 새로운 클로징 오더가 배치되며 업데이트 된 현재 가격에 인크리시 오더가 배치되지만 추가 포지션에 대한 오더 볼륨은 두 배로 증가하지 않습니다.
초기 작업 대기 중인 주문 때문에, 우리는 주문 ID를 기록하기 위해 두 개의 글로벌 변수가 필요합니다.
var buyOrderId = null
var sellOrderId = null
그런 다음 전략 인터페이스 매개 변수는 OKEX_V5 시뮬레이션 봇 옵션을 사용하도록 설계되어 있으므로 코드에 약간의 처리 작업이 필요합니다.
var exName = exchange.GetName()
// Switch OKEX V5 simulated bot
if (isSimulate && exName == "Futures_OKCoin") {
exchange.IO("simulate", true)
}
또한 인터페이스 매개 변수에서 모든 정보를 재설정할 수 있는 옵션이 있습니다. 따라서 코드에 대응하는 처리가 있어야 합니다.
if (isReset) {
_G(null)
LogReset(1)
LogProfitReset()
LogVacuum()
Log("reset all data", "#FF0000")
}
우리는 영구 계약만 실행합니다. 그래서 글은 여기에 고정되어 영구으로 설정됩니다.
exchange.SetContractType("swap")
또한 주문 가격과 주문 금액의 정확성을 고려해야합니다. 정확도가 올바르게 설정되지 않으면 전략 계산 과정에서 정확도가 손실됩니다. 데이터가 많은 소수점을 가지고 있다면 거래소 인터페이스에 의해 주문이 거부되는 것이 쉽습니다.
exchange.SetPrecision(pricePrecision, amountPrecision)
Log("set precision", pricePrecision, amountPrecision)
설계에 의해 간단한 데이터 복구
if (totalEq == -1 && !IsVirtual()) {
var recoverTotalEq = _G("totalEq")
if (!recoverTotalEq) {
var currTotalEq = getTotalEquity()
if (currTotalEq) {
totalEq = currTotalEq
_G("totalEq", currTotalEq)
} else {
throw "failed to obtain initial equity"
}
} else {
totalEq = recoverTotalEq
}
}
만약 당신이 전략을 실행할 때 계좌의 초기 총 자산을 지정하고 싶다면, 당신은 매개 변수를 설정할 수 있습니다totalEq
이 매개 변수를 -1로 설정하면 전략은 저장된 총 주식 데이터를 읽는다. 저장된 총 주식 데이터가 없다면, 현재 읽힌 총 주식은 진행 중인 전략의 초기 총 주식으로 사용됩니다. 그 후 총 주식의 증가는 이익을 나타내고, 총 주식의 감소는 손실을 나타냅니다. 총 주식 데이터가 읽히면 전략은이 데이터로 계속 실행됩니다.
주요 논리 초기 작업이 완료된 후, 마침내 우리는 전략의 주요 논리 부분으로 왔습니다. 설명의 편의를 위해, 나는 코드 댓글에 직접 지침을 썼다.
while (1) { // The main logic of the strategy is designed as an infinite loop
var ticker = _C(exchange.GetTicker) // Read the current market information first, mainly using the latest transaction price
var pos = _C(exchange.GetPosition) // Read current position data
if (pos.length > 1) { // Judging the position data, because of the logic of this strategy, it is unlikely that long and short positions will appear at the same time, so if there are long and short positions at the same time, an error will be thrown
Log(pos)
throw "Simultaneous long and short positions" // Throw an error to stop the strategy
}
//Depends on status
if (pos.length == 0) { // Make different operations according to the position status, when there is no position, pos.length == 0
// If you have not held a position, count the profit once
if (!IsVirtual()) {
var currTotalEq = getTotalEquity()
if (currTotalEq) {
LogProfit(currTotalEq - totalEq, "current total equity:", currTotalEq)
}
}
buyOrderId = openLong(ticker.Last - targetProfit, amount) // Open a buy order for a long position
sellOrderId = openShort(ticker.Last + targetProfit, amount) // Open a short sell order
} else if (pos[0].Type == PD_LONG) { // For long positions, the position and quantity of pending orders are different
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) { // For short positions, the position and quantity of pending orders are different
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) { // If one side of the pending order fails, cancel all pending orders and start over
cancelAll()
buyOrderId = null
sellOrderId = null
continue
}
while (1) { // The pending order is completed, start monitoring the order
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) { // Detected that both buy and sell orders have been filled
cancelAll()
break
} else if (!isFindBuyId) { // Detected buy order closing
Log("buy order closing")
cancelAll()
break
} else if (!isFindSellId) { // Detected sell order closing
Log("sell order closing")
cancelAll()
break
}
LogStatus(_D())
Sleep(3000)
}
Sleep(500)
}
모든 논리와 설계가 설명되어 있습니다.
전략이 5월 19일 시장에서 통과하도록 하자.
마르틴게일 전략은 여전히 어떤 위험을 안고 있다는 것을 알 수 있습니다.
실제 로봇은 OKEX V5 시뮬레이션 로봇으로 실행될 수 있습니다.
전략 주소:https://www.fmz.com/strategy/294957
전략은 주로 학습을 위해 사용되며 실제 돈은 조심스럽게 사용해야 합니다~!