이전 기사에서 우리는 간단한 헤지 전략을 함께 구현했고, 그 다음 전략을 업그레이드하는 방법을 배우게 될 것입니다. 전략에는 많은 변경 사항이 없지만 변경 사항의 세부 사항에 주의가 필요합니다. 코드 내의 일부 장소의 정의는 이전 것과 비교하여 수정되었습니다. 구체적으로 이해해야합니다.
A->B
그리고B->A
, 수평 스프레드 트리거 라인뿐만 아니라, 우리는 직접 사용할 수 있습니다chart plot library
; 장점은 단순성과 사용 편리함입니다. 여기서 우리는 또한 FMZ의 기능을 사용하는 방법을 배울 수 있습니다.template library
together.다음으로, 그 디자인 아이디어를 하나씩 실현해 보겠습니다.
예를 들어 Binance 스팟 봇을 들어보자. 스팟 마진 모드로 전환하려면 코드를 사용exchanges[i].IO
, 매개 변수를 가져오trade_normal
격리된 마진으로 전환하고 수입trade_super_margin
cross margin로 전환했습니다. backtest에서는 지원되지 않습니다. 보트에서만 사용할 수 있습니다.
그 시작에 준비에서main
함수, 추가:
// switch the margin mode
for (var i = 0 ; i < exchanges.length ; i++) { // traverse and detect all exchange objects added
if (exchanges[i].GetName() == "Binance" && marginType != 0) { // if the exchange object represented by the current index i is Binance Spot, and the parameter marginType on the strategy interface is not selected as the "common spot" option, execute the switch
if (marginType == 1) {
Log(exchanges[i].GetName(), "set to isolated margin")
exchanges[i].IO("trade_normal")
} else if (marginType == 2) {
Log(exchanges[i].GetName(), "set to cross margin")
exchanges[i].IO("trade_super_margin")
}
}
}
여기서 전략은 Binance Spot의 스팟 마진 모드를 전환하는 코드를 추가합니다. 따라서 전략 매개 변수에서 스위치 설정은 Binance Spot에서만 작동합니다.
캡슐화된 플롯링 템플릿을 사용하는 것은 매우 간단합니다. 우리가 여기서 사용하는 템플릿 이름은chart plot Library
FMZ 광장 플랫폼에서 직접 검색할 수 있습니다.
또는 이 링크를 직접 클릭할 수도 있습니다.https://www.fmz.com/strategy/27293템플릿의 복사 페이지로 넘어가면 됩니다.
버튼을 클릭하면 자신의 전략 라이브러리에 쉽게 템플릿을 복사 할 수 있습니다.
다음, 전략 편집 페이지에서, 당신은 템플릿 열에서 사용할 템플릿 라이브러리를 확인할 수 있습니다. 그것을 확인 한 후 전략을 저장, 그리고 전략이 이 템플릿을 사용할 것입니다. 이것은 단지 템플릿 라이브러리의 사용에 대한 간략한 설명입니다. 전략이 이미 이 템플릿을 참조했기 때문에, 작업을 반복할 필요가 없습니다. 당신이 스퀘어에 전략 코드를 복사하면, 당신은 볼 수 있습니다chart plot Library
전략 편집 페이지의 템플릿 바에 참조되었습니다.
여기서 우리는 주로chart plot library
음모를 꾸미기 위해서요.
우리는 스프레드를 계획합니다A->B
그리고B->A
, 그리고 스프레드의 트리거 라인입니다. 우리는 위의 그림과 같이 두 개의 곡선 (현재 A에서 B, B에서 A까지의 스프레드) 과 두 개의 수평선 (스프레드 트리거 라인) 을 그리어야 합니다.
왜냐하면 우리는 단면적 헤지를 설계하고 싶어하기 때문에A->B
그리고B->A
다른 것이 될 것입니다. 그리고 우리는 이전 기사에서 디자인을 사용할 수 없습니다.
이전 기사 에서:
var targetDiffPrice = hedgeDiffPrice
if (diffAsPercentage) {
targetDiffPrice = (depthA.Bids[0].Price + depthB.Asks[0].Price + depthB.Bids[0].Price + depthA.Asks[0].Price) / 4 * hedgeDiffPercentage
}
한 번의 트리거 스프레드가 있습니다.targetDiffPrice
- 네
따라서 여기서 코드를 수정해야 합니다. 먼저 매개 변수를 수정해야 합니다.
다음 코드를 수정합니다:
var targetDiffPriceA2B = hedgeDiffPriceA2B
var targetDiffPriceB2A = hedgeDiffPriceB2A
if (diffAsPercentage) {
targetDiffPriceA2B = (depthA.Bids[0].Price + depthB.Asks[0].Price + depthB.Bids[0].Price + depthA.Asks[0].Price) / 4 * hedgeDiffPercentageA2B
targetDiffPriceB2A = (depthA.Bids[0].Price + depthB.Asks[0].Price + depthB.Bids[0].Price + depthA.Asks[0].Price) / 4 * hedgeDiffPercentageB2A
}
따라서, 확산 트리거 라인은 이전 하나에서 변경되었습니다targetDiffPrice
두 가지로,targetDiffPriceA2B
그리고targetDiffPriceB2A
- 네
다음으로, 차트 플롯 라이브러리의 차트 플롯 함수를 사용하여 차트에 데이터를 그려볼 수 있습니다.
// plot
$.PlotHLine(targetDiffPriceA2B, "A->B") // the first parameter of the function is the value of the horizontal line in the Y-axis direction, and the second parameter is the display text
$.PlotHLine(targetDiffPriceB2A, "B->A")
전략이 실행되면 이 그래프가 이렇게 표시됩니다.
다음으로, 실시간 스프레드 곡선을 그리세요. 너무 많이 그리지 않으려면, 실시간 스프레드 곡선을 그래프로 그리는 코드를 균형 감지에 넣으십시오. s
if (ts - lastKeepBalanceTS > keepBalanceCyc * 1000) {
nowAccs = _C(updateAccs, exchanges)
var isBalance = keepBalance(initAccs, nowAccs, [depthA, depthB])
cancelAll()
if (isBalance) {
lastKeepBalanceTS = ts
if (isTrade) {
var nowBalance = _.reduce(nowAccs, function(sumBalance, acc) {return sumBalance + acc.Balance}, 0)
var initBalance = _.reduce(initAccs, function(sumBalance, acc) {return sumBalance + acc.Balance}, 0)
LogProfit(nowBalance - initBalance, nowBalance, initBalance, nowAccs)
isTrade = false
}
}
$.PlotLine("A2B", depthA.Bids[0].Price - depthB.Asks[0].Price) // plot real-time spread curves
$.PlotLine("B2A", depthB.Bids[0].Price - depthA.Asks[0].Price) // the first parameter is the curve name, and the second parameter is the curve value at the current moment, that is, the value in the Y-axis direction at the current moment
}
그래핑 코드는 실행 중 차트 디스플레이로 전략을 허용하기 위해 4줄만 필요합니다.
앞서 언급했듯이 스프레드 트리거 라인의 숫자는 각각 두 개로 변경되었습니다.A->B
그리고B->A
이 방법으로 이전 주문 가격 알고리즘을 사용할 수 없으며 시장 가격에 슬라이드 가격을 추가하는 방법을 사용합니다.
if (depthA.Bids[0].Price - depthB.Asks[0].Price > targetDiffPriceA2B && Math.min(depthA.Bids[0].Amount, depthB.Asks[0].Amount) >= minHedgeAmount) { // A->B market condition satisfied
var priceSell = depthA.Bids[0].Price - slidePrice
var priceBuy = depthB.Asks[0].Price + slidePrice
var amount = Math.min(depthA.Bids[0].Amount, depthB.Asks[0].Amount)
if (nowAccs[0].Stocks > minHedgeAmount && nowAccs[1].Balance * 0.8 / priceSell > minHedgeAmount) {
amount = Math.min(amount, nowAccs[0].Stocks, nowAccs[1].Balance * 0.8 / priceSell, maxHedgeAmount)
Log("triggerA->B:", depthA.Bids[0].Price - depthB.Asks[0].Price, priceBuy, priceSell, amount, nowAccs[1].Balance * 0.8 / priceSell, nowAccs[0].Stocks) // prompt message
hedge(exB, exA, priceBuy, priceSell, amount)
cancelAll()
lastKeepBalanceTS = 0
isTrade = true
}
} else if (depthB.Bids[0].Price - depthA.Asks[0].Price > targetDiffPriceB2A && Math.min(depthB.Bids[0].Amount, depthA.Asks[0].Amount) >= minHedgeAmount) { // B->A market condition satisfied
var priceBuy = depthA.Asks[0].Price + slidePrice
var priceSell = depthB.Bids[0].Price - slidePrice
var amount = Math.min(depthB.Bids[0].Amount, depthA.Asks[0].Amount)
if (nowAccs[1].Stocks > minHedgeAmount && nowAccs[0].Balance * 0.8 / priceBuy > minHedgeAmount) {
amount = Math.min(amount, nowAccs[1].Stocks, nowAccs[0].Balance * 0.8 / priceBuy, maxHedgeAmount)
Log("triggerB->A:", depthB.Bids[0].Price - depthA.Asks[0].Price, priceBuy, priceSell, amount, nowAccs[0].Balance * 0.8 / priceBuy, nowAccs[1].Stocks) // prompt message
hedge(exA, exB, priceBuy, priceSell, amount)
cancelAll()
lastKeepBalanceTS = 0
isTrade = true
}
}
구매 및 판매 가격이 두 개의 데이터로 나뉘어 있기 때문에,hedge
기능도 수정해야 합니다.
function hedge(buyEx, sellEx, priceBuy, priceSell, amount) {
var buyRoutine = buyEx.Go("Buy", priceBuy, amount)
var sellRoutine = sellEx.Go("Sell", priceSell, amount)
Sleep(500)
buyRoutine.wait()
sellRoutine.wait()
}
또한 이 변경 사항에 기초한 몇 가지 작은 조정도 있습니다. 여기서 설명하지 않겠습니다. 자세한 내용은 코드에서 볼 수 있습니다.
전략에 상호 작용을 추가하여 전략이 실시간으로 스프레드 트리거 라인을 수정할 수 있습니다. 이것은 또한 반 자동 전략의 설계 요구 사항입니다. 전략 상호 작용 디자인 또한 매우 간단합니다. 먼저, 전략 편집 페이지에서 전략에 상호 작용 컨트롤을 추가합니다.
두 개의 컨트롤이 추가되었습니다. 하나는 A2B, 다른 하나는 B2A라고 불립니다. 컨트롤 입력 상자에 값을 입력 한 후 입력 상자의 오른쪽에있는 버튼을 클릭하십시오. 명령어는 즉시 전략에 전송됩니다. 예를 들어: 값을 입력123
입력 상자에서A2B
버튼을 누르면 즉시 전략에 명령이 보내집니다.
A2B:123
전략 코드에서 대화형 탐지 및 처리 코드를 설계합니다.
// interaction
var cmd = GetCommand() // every time when the loop is operated here, it will detect whether an interactive command is sent; if no, return null string
if (cmd) { // interactive command detected, such as A2B:123
Log("received command:", cmd)
var arr = cmd.split(":") // split out the interactive control name and the value in the input box; arr[0] means A2B, and arr[1] means 123
if (arr[0] == "A2B") { // judge whether the triggered interactive control is A2B
Log("modify parameterA2B,", diffAsPercentage ? "parameter of spread ratio:" : "parameter of spread:", arr[1])
if (diffAsPercentage) {
hedgeDiffPercentageB2A = parseFloat(arr[1]) // modify the spread trigger line
} else {
hedgeDiffPriceA2B = parseFloat(arr[1]) // modify the spread trigger line
}
} else if (arr[0] == "B2A") { // detected the triggered control is B2A
Log("modify parameterB2A,", diffAsPercentage ? "parameter of spread ratio:" : "parameter of spread:", arr[1])
if (diffAsPercentage) {
hedgeDiffPercentageA2B = parseFloat(arr[1])
} else {
hedgeDiffPriceB2A = parseFloat(arr[1])
}
}
}
상태 표시줄 데이터를 더 조절하고 쉽게 관찰 할 수 있습니다.
var tbl = {
"type" : "table",
"title" : "data",
"cols" : ["platform", "Currency", "frozenCurrrency", "quoteCurrency", "frozenQuoteCurrency", "triggerSpread", "currentSpread"],
"rows" : [],
}
tbl.rows.push(["A:" + exA.GetName(), nowAccs[0].Stocks, nowAccs[0].FrozenStocks, nowAccs[0].Balance, nowAccs[0].FrozenBalance, "A->B:" + targetDiffPriceA2B, "A->B:" + (depthA.Bids[0].Price - depthB.Asks[0].Price)])
tbl.rows.push(["B:" + exB.GetName(), nowAccs[1].Stocks, nowAccs[1].FrozenStocks, nowAccs[1].Balance, nowAccs[1].FrozenBalance, "B->A:" + targetDiffPriceB2A, "B->A:" + (depthB.Bids[0].Price - depthA.Asks[0].Price)])
LogStatus(_D(), "\n", "`" + JSON.stringify(tbl) + "`")
백테스트는 초기 탐지 기능으로 전략의 테스트에 불과합니다. 많은 버그가 실제로 백테스트 단계에서 테스트 될 수 있습니다. 백테스트 결과에 대해 너무 신경 쓸 필요가 없습니다. 결국 전략은 여전히 실제 환경에서 실제 봇과 테스트해야합니다.
전략 소스 코드:https://www.fmz.com/strategy/302834