이윤 수확자 전략 분석 (2)

저자:니나바다스, 창작: 2022-04-26 15:57:02, 업데이트: 2022-04-26 15:57:53

이윤 수확자 전략 분석 (2)

계속해 봅시다지난번의 내용설명할 수 있습니다.

세 번째 추가 기능:

    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(수준 정보로서 구매 주문 목록에 유효해야 하는 깊이 데이터)

명령어 if의 조건이 트리거되면 실행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.preNettrue, 속성을 업데이트합니다.self.preNet순액을 기록하는net그 다음, 전체 순 가치 데이터를 인쇄netFMZ 양자 거래 플랫폼 봇의 이익 곡선 차트에 (당신은LogProfitFMZ 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밀리초를 기다립니다. 루프는orderIdtrue입니다 (오더가 실패하면 오더 ID는 반환되지 않으며 if 조건은 트리거되지 않습니다.) 조건이 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.numTick0으로

건설자의 마지막 실행LeeksReaper()를 반환 합니다self물체, 즉,var reaper = LeeksReaper(), 객체가 반환됩니다reaper.

현재까지 우리는LeeksReaper()컨스트럭터 (constructor) 는 이 수익 수확자 객체, 객체의 다양한 방법, 그리고 주요 논리 함수의 실행 프로세스를 구성합니다. 기사를 읽은 후, 나는 당신이 고주파 전략 알고리즘 프로세스에 대한 더 명확한 이해를 가질 것이라고 생각합니다.


더 많은