계속해 봅시다지난번의 내용설명할 수 있습니다.
세 번째 추가 기능:
self.balanceAccount = function() {
var account = exchange.GetAccount()
if (!account) {
return
}
self.account = account
var now = new Date().getTime()
if (self.orderBook.Bids.length > 0 && now - self.preCalc > (CalcNetInterval * 1000)) {
self.preCalc = now
var net = _N(account.Balance + account.FrozenBalance + self.orderBook.Bids[0].Price * (account.Stocks + account.FrozenStocks))
if (net != self.preNet) {
self.preNet = net
LogProfit(net)
}
}
self.btc = account.Stocks
self.cny = account.Balance
self.p = self.btc * self.prices[self.prices.length-1] / (self.btc * self.prices[self.prices.length-1] + self.cny)
var balanced = false
if (self.p < 0.48) {
Log("start to balance", self.p)
self.cny -= 300
if (self.orderBook.Bids.length >0) {
exchange.Buy(self.orderBook.Bids[0].Price + 0.00, 0.01)
exchange.Buy(self.orderBook.Bids[0].Price + 0.01, 0.01)
exchange.Buy(self.orderBook.Bids[0].Price + 0.02, 0.01)
}
} else if (self.p > 0.52) {
Log("start to balance", self.p)
self.btc -= 0.03
if (self.orderBook.Asks.length >0) {
exchange.Sell(self.orderBook.Asks[0].Price - 0.00, 0.01)
exchange.Sell(self.orderBook.Asks[0].Price - 0.01, 0.01)
exchange.Sell(self.orderBook.Asks[0].Price - 0.02, 0.01)
}
}
Sleep(BalanceTimeout)
var orders = exchange.GetOrders()
if (orders) {
for (var i = 0; i < orders.length; i++) {
if (orders[i].Id != self.tradeOrderId) {
exchange.CancelOrder(orders[i].Id)
}
}
}
}
설계자가LeeksReaper()
객체를 구성하고 있습니다.balanceAccount()
객체에 추가된 함수는 계정 자산 정보를 업데이트하는 데 사용됩니다.self.account
, 즉, 그 속성을 구성account
물체의. 계산하고 정기적으로 반환 값을 인쇄. 다음, 최신 계정 자산 정보에 따라, 현금 통화 기호의 잔액 비율 (현금 위치 잔액) 는 계산되며, 오프셋 임계값이 트리거되면, 작은 주문이 닫혀서 기호 (상위) 를 균형 상태로 되돌립니다. 거래를 실행하기 위해 일정 기간을 기다립니다. 그리고 모든 미뤄진 명령을 취소하고 다음 라운드에서 기능을 실행하면 잔액이 다시 감지되고 그에 따른 처리가 수행됩니다.
이 함수 명령어의 코드를 명령어별로 살펴봅시다:
우선, 첫 번째 진술은var account = exchange.GetAccount()
로컬 변수를 선언합니다account
"라고 부르고 있습니다.exchange.GetAccount()
FMZ API 인터페이스에서 기능, 현금 계좌의 최신 데이터를 얻고 변수에 할당account
그럼 변수를 판단해account
만약 변수 값이null
(타임오웃, 네트워크, 플랫폼 인터페이스 예외 등과 같은 변수를 얻지 못할 때 일어날 것입니다), 그것은 직접 (대응하는) 반환됩니다.if (!account ){...}
여기).
진술서self.account = account
로컬 변수를 할당하는 것입니다account
속성account
건설된 객체에서 최신 계정 정보를 기록하기 위해
진술서var now = new Date().getTime()
로컬 변수를 선언합니다now
, 그리고 호출getTime()
자바스크립트 언어의 시간 & 날짜 객체의 함수로 현재 시간표를 반환하고 변수에 시간표를 할당합니다now
.
코드:if (self.orderBook.Bids.length > 0 && now - self.preCalc > (CalcNetInterval * 1000)) {...}
현재 시간표와 마지막으로 기록된 시간표 사이의 차이를 판단합니다. 값이 매개 변수를 초과하면CalcNetInterval * 1000
, 그것은 그것이 초과되었다는 것을 의미합니다CalcNetInterval * 1000
밀리초 (CalcNetInterval
마지막 업데이트에서 현재까지, 주기적으로 수익을 인쇄하는 기능을 실현. 시장에서 구매 1 가격을 사용할 필요가 있기 때문에 수익을 계산 할 때, 조건은 또한 조건에 제한됩니다.self.orderBook.Bids.length > 0
(수준 정보로서 구매 주문 목록에 유효해야 하는 깊이 데이터)
명령어 self.preCalc = now
타임 스탬프 변수를 업데이트하기 위해self.preCalc
최근 인쇄된 이익의 현재 시간표now
이 경우, 이윤 통계는 순가치 계산 방법을 사용합니다. 코드는:var net = _N(account.Balance + account.FrozenBalance + self.orderBook.Bids[0].Price * (account.Stocks + account.FrozenStocks))
즉, 현재 구매 1 가격에 따라 화폐를 자산으로 변환하고 계정에서의 자산 금액과 합쳐서 선언된 로컬 변수에 할당합니다.net
현재 총 순액이 마지막으로 기록된 총 순액과 일치하는지 확인합니다.
if (net != self.preNet) {
self.preNet = net
LogProfit(net)
}
불일치하면, 즉net != self.preNet
true, 속성을 업데이트합니다.self.preNet
순액을 기록하는net
그 다음, 전체 순 가치 데이터를 인쇄net
FMZ 양자 거래 플랫폼 봇의 이익 곡선 차트에 (당신은LogProfit
FMZ API 문서에 있는 기능)
반환의 정규 인쇄가 시작되지 않는 경우 다음 프로세스를 계속: 기록account.Stocks
(계산에 있는 현재 사용 가능한 통화 기호)account.Balance
(계산의 현재 사용 가능한 자산)self.btc
그리고self.cny
오프셋 비율을 계산하고 그것을 할당합니다.self.p
.
self.p = self.btc * self.prices[self.prices.length-1] / (self.btc * self.prices[self.prices.length-1] + self.cny)
알고리즘은 또한 매우 간단합니다. 현재 통화 가치의 몇 퍼센트가 계좌의 총 순액에 있는지 계산하는 것입니다.
그래서 어떻게 통화 (포지션) 잔액이 발생했을 때 판단합니까?
여기 개발자는 50%를 사용 하 고 아래로 2 퍼센트 포인트를 버퍼로; 그것은 버퍼를 초과하는 경우, 균형을 실행, 즉,self.p < 0.48
, 통화 잔액의 오프셋이 시작됩니다. 당신이 통화 금액이 작다고 생각하면, 가격이 0.01 증가할 때마다, 세 개의 작은 명령을합니다. 마찬가지로, 통화 잔액이 작은 경우self.p > 0.52
, 당신이 통화 금액이 크다고 생각하면, 시장에서 판매 1 가격의 작은 주문을 기다립니다. 마지막으로, 파라미터 설정에 따라 일정 기간 동안 기다립니다.Sleep(BalanceTimeout)
그리고 모든 주문을 취소합니다.
var orders = exchange.GetOrders() # obtain all the current pending orders, and save them in the variable orders"
if (orders) { # if the variable "orders", which obtains all the current pending orders, is not null
for (var i = 0; i < orders.length; i++) { # use the loop to traverse "orders", and cancel the orders one by one
if (orders[i].Id != self.tradeOrderId) {
exchange.CancelOrder(orders[i].Id) # call "exchange.CancelOrder", and cancel orders by "orders[i].Id"
}
}
}
네 번째 추가 기능:
여기 전략의 핵심 부분, 하이라이트가 있습니다.self.poll = function() {...}
기능은 전체 전략의 주요 논리입니다. 우리는 또한 이전 기사에서 그것에 대해 이야기했습니다.main( )
함수, 실행하기 시작하기 전에while
무궁무진한 루프, 우리는 사용var reaper = LeeksReaper()
이윤 수확자 객체를 구축하고,Reaper.poll()
회전적으로 불립니다main()
function.
이self.poll
함수가 실행되기 시작하고, 각 루프 전에 몇 가지 준비를 합니다.self.numTick++
수를 증가시킵니다.self.updateTrades()
최근 시장에서의 거래 기록을 업데이트하고 사용된 관련 데이터를 계산합니다.self.updateOrderBook()
시장 (오더 포스) 데이터를 업데이트하고 관련 데이터를 계산합니다.self.balanceAccount()
통화 (포지션) 잔액을 확인합니다.
var burstPrice = self.prices[self.prices.length-1] * BurstThresholdPct # calculate the burst price
var bull = false # declare the variable marked by the bull market; the initial value is false
var bear = false # declare the variable marked by the bear market; the initial value is false
var tradeAmount = 0 # declare the variable of trading amount; the initial value is 0
다음으로, 우리는 현재의 단기 시장이 황소인지 곰인지 판단해야 합니다.
if (self.numTick > 2 && (
self.prices[self.prices.length-1] - _.max(self.prices.slice(-6, -1)) > burstPrice ||
self.prices[self.prices.length-1] - _.max(self.prices.slice(-6, -2)) > burstPrice && self.prices[self.prices.length-1] > self.prices[self.prices.length-2]
)) {
bull = true
tradeAmount = self.cny / self.bidPrice * 0.99
} else if (self.numTick > 2 && (
self.prices[self.prices.length-1] - _.min(self.prices.slice(-6, -1)) < -burstPrice ||
self.prices[self.prices.length-1] - _.min(self.prices.slice(-6, -2)) < -burstPrice && self.prices[self.prices.length-1] < self.prices[self.prices.length-2]
)) {
bear = true
tradeAmount = self.btc
}
기억하시나요?self.updateOrderBook()
전 기사에서, 우리는 시간 계열을 구성하는 가중 평균 알고리즘을 사용prices
배열 순서? 이 코드 조각은 세 가지 새로운 기능을 사용합니다._.min
, _.max
, slice
, 또한 매우 쉽게 이해할 수 있습니다.
_.min
: 함수는 매개 변수 배열의 최소를 찾는 것입니다.
_.max
: 함수는 매개 변수 배열의 최대값을 찾는 것입니다.
slice
: 이 함수는 자바스크립트 배열 객체의 멤버 함수입니다. 그것은 인덱스에 따라 배열의 일부를 가로채고 반환합니다. 예를 들어:
function main() {
// index .. -8 -7 -6 -5 -4 -3 -2 -1
var arr = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
Log(arr.slice(-5, -1)) // it will intercept several elements from 4 to 1, and return a new array: [4,3,2,1]
}
여기서는 황소시장인지 곰시장인지 판단하는 조건은 다음과 같습니다.
self.numTick > 2
즉, 새로운 탐지 라운드에서 가격 폭발이 발생하면 적어도 세 번의 탐지 라운드 후에 촉발되어야 하며, 시작에서 촉발을 피해야 합니다.self.prices
, 즉 최신 데이터와 최대 또는 최소 가격의 차이self.prices
이전 범위의 배열은burstPrice
.모든 조건이 사실이라면, 표시bull
또는bear
그 외true
, 그리고 변수에 값을 부여tradeAmount
, 그리고 종을 거래할 계획을 세웠어요.
그럼, 매개 변수BurstThresholdVol
,self.vol
이전에서 업데이트 및 계산self.updateTrades()
거래 강도를 줄이거나 (계획된 거래량을 줄이거나) 결정됩니다.
if (self.vol < BurstThresholdVol) {
tradeAmount *= self.vol / BurstThresholdVol // reduce the planned trading volume, and reduce it to the previous volume multiplied by "self.vol / BurstThresholdVol"
}
if (self.numTick < 5) {
tradeAmount *= 0.8 // reduced to 80% of the plan
}
if (self.numTick < 10) { // reduced to 80% of the plan
tradeAmount *= 0.8
}
다음으로 거래 신호와 거래 부피가 요구 사항을 충족하는지 판단합니다.
if ((!bull && !bear) || tradeAmount < MinStock) { # if it is not a bull market nor a bear market, or the planned trading volume "tradeAmount" is less than the minimum trading volume "MinStock" set by the parameter, the "poll" function returns directly without any trading operation
return
}
위 판결 후, 집행var tradePrice = bull ? self.bidPrice : self.askPrice
- 마이너스 마켓 또는 올 마켓에 따라 거래 가격을 설정하고 해당 배달 주문 가격과 값을 할당합니다.
마지막으로, 입력while
루프: 루프의 유일한 정지 및 휴식 조건은tradeAmount >= MinStock
즉, 계획된 거래량은 최소 거래량보다 적습니다.
루프에서, 현재 황소 시장 상태 또는 곰 시장 상태에 따라, 명령을 실행. 그리고 변수에 주문 ID를 기록orderId
처형하라Sleep(200)
라운드마다 주문을 한 후 200밀리초를 기다립니다. 루프는orderId
true입니다 (오더가 실패하면 오더 ID는 반환되지 않으며 self.tradeOrderId
.
변수를 선언합니다order
의 초기 값으로 주문 데이터를 저장하기 위해null
. 다음, 순서 데이터를 얻기 위해 루프를 사용 하 여 ID를, 그리고 순서가 대기 순서 상태에 있는지 결정; 그것은 대기 순서 상태에 있는 경우, ID와 순서를 취소; 그것은 대기 순서 상태에 없는 경우, 그것은 탐지 루프에서 깨질 것입니다.
var order = null // declare a variable to save the order data
while (true) { // a while loop
order = exchange.GetOrder(orderId) // call "GetOrder" to query the order data with the ID of orderId
if (order) { // if the order data is queried,and the query fails, the order is null, and "if" will not be triggered
if (order.Status == ORDER_STATE_PENDING) { // judge whether the current order status is pending order
exchange.CancelOrder(orderId) // if the current order status is pending order, cancel the order
Sleep(200)
} else { // if not, execute "break" to break out of the while loop
break
}
}
}
다음 절차를 수행합니다.
self.tradeOrderId = 0 // reset "self.tradeOrderId"
tradeAmount -= order.DealAmount // update "tradeAmount", and subtract the executed amount of the orders in the delivery order
tradeAmount *= 0.9 // reduce the intensity of ordering
if (order.Status == ORDER_STATE_CANCELED) { // if the order is canceled
self.updateOrderBook() // update the data, including the order book data
while (bull && self.bidPrice - tradePrice > 0.1) { // in a bull market, if the updated bid price exceeds the current trading price by 0.1, reduce the trading intensity, and slightly adjust the trading price
tradeAmount *= 0.99
tradePrice += 0.1
}
while (bear && self.askPrice - tradePrice < -0.1) { // in a bear market, if the updated ask price exceeds the current trading price by 0.1, reduce the trading intensity, and slightly adjust the trading price
tradePrice -= 0.1
}
}
프로그램 흐름이while (tradeAmount >= MinStock) {...}
루프, 그것은 가격 폭발 거래 프로세스의 실행이 완료되었다는 것을 의미합니다.
실행self.numTick = 0
즉, 재설정self.numTick
0으로
건설자의 마지막 실행LeeksReaper()
를 반환 합니다self
물체, 즉,var reaper = LeeksReaper()
, 객체가 반환됩니다reaper
.
현재까지 우리는LeeksReaper()
컨스트럭터 (constructor) 는 이 수익 수확자 객체, 객체의 다양한 방법, 그리고 주요 논리 함수의 실행 프로세스를 구성합니다. 기사를 읽은 후, 나는 당신이 고주파 전략 알고리즘 프로세스에 대한 더 명확한 이해를 가질 것이라고 생각합니다.