
그 다음에이전 내용설명하다.
세 번째로 추가된 기능:
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("开始平衡", 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("开始平衡", 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, 발명가 API 인터페이스를 호출합니다.exchange.GetAccount()함수, 현재 계정의 최신 데이터를 가져와서 할당합니다.account변하기 쉬운. 그럼 판단해 보세요account이 변수는 변수가 다음과 같은 경우null값(예: 타임아웃, 네트워크, 교환 인터페이스 예외 등)을 얻지 못하면 해당 값이 직접 반환됩니다(다음에 해당).if (!account){...}여기).
self.account = account이 문장은 지역 변수를 넣는 것입니다account구성된 객체에 할당됨account속성은 생성된 객체의 최신 계정 정보를 기록하는 데 사용됩니다.
var now = new Date().getTime()이 문장은 지역 변수를 선언합니다.now, JavaScript 언어의 시간 및 날짜 객체를 호출합니다.getTime()해당 함수는 현재 타임스탬프를 반환합니다. 할당하다now변하기 쉬운.
if (self.orderBook.Bids.length > 0 && now - self.preCalc > (CalcNetInterval * 1000)) {...}이 코드는 현재 타임스탬프와 마지막으로 기록된 타임스탬프의 차이가 매개변수를 초과하는지 여부를 판별합니다.CalcNetInterval * 1000이는 마지막 업데이트부터 지금까지CalcNetInterval * 1000밀리초(CalcNetInterval초), 수입 인쇄 타이밍 기능을 달성하기 위해. 수입을 계산할 때 첫 번째 입찰 가격이 사용되므로 조건도 제한됩니다.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))즉, 현재 매수가에 따라 코인을 돈(분모)으로 환산한 후, 이를 계좌의 돈 금액에 더하여 선언된 지역변수에 할당합니다.net. 현재 순총액이 지난번에 기록된 순총액과 일치하는지 확인하세요.
if (net != self.preNet) {
self.preNet = net
LogProfit(net)
}
일관성이 없다면,net != self.preNet사실이라면 사용하세요net변수 업데이트는 순 가치의 속성을 기록하는 데 사용됩니다.self.preNet. 그런 다음 이것을 인쇄하세요net발명가의 양적 거래 플랫폼 로봇의 이익 곡선 차트에 대한 총 순자산 데이터(FMZ API 문서에서 쿼리 가능)LogProfit이 기능).
예약된 인쇄 수익이 발생하지 않으면 다음 프로세스를 계속 진행합니다.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씩 올리면서 소액 주문을 3회 내세요. 마찬가지로 통화 균형self.p > 0.52, 코인이 너무 많다고 생각되면 시작가에 매도하여 소액 주문을 낼 수 있습니다. 마지막으로 파라미터 설정에 따라 일정시간 기다려주세요Sleep(BalanceTimeout)모든 주문은 이후 취소됩니다.
var orders = exchange.GetOrders() # 获取当前所有挂单,存在orders变量
if (orders) { # 如果获取当前挂单数据的变量orders不为null
for (var i = 0; i < orders.length; i++) { # 循环遍历orders,逐个取消订单
if (orders[i].Id != self.tradeOrderId) {
exchange.CancelOrder(orders[i].Id) # 调用exchange.CancelOrder,根据orders[i].Id取消订单
}
}
}
네 번째로 추가된 기능:
전략의 핵심 부분, 하이라이트는 여기에 있습니다.self.poll = function() {...}기능은 전체 전략의 주요 논리입니다. 이전 기사에서도 이에 대해 이야기했습니다.main()함수가 실행을 시작하고 들어갑니다.while무한 루프 전에 우리는 다음을 사용합니다.var reaper = LeeksReaper()부추 수확기 객체를 구성한 다음main()함수에서 루프 호출reaper.poll()호출되는 함수입니다.
self.poll해당 함수는 실행을 시작하고 각 루프 전에 몇 가지 준비 작업을 수행합니다.self.numTick++카운트를 늘리다,self.updateTrades()최신 시장 거래 기록을 업데이트하고 관련 데이터를 계산합니다.self.updateOrderBook()주문장부 데이터를 업데이트하고 관련 데이터를 계산합니다.self.balanceAccount()자금(포지션) 잔액을 확인하세요.
var burstPrice = self.prices[self.prices.length-1] * BurstThresholdPct # 计算爆发价格
var bull = false # 声明牛市标记的变量,初始为假
var bear = false # 声明熊市标记的变量,初始为假
var tradeAmount = 0 # 声明交易数量变量,初始为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: 이 함수는 JavaScript 배열 객체의 멤버 함수입니다. 이 함수의 기능은 인덱스에 따라 배열의 일부를 가로채서 반환하는 것입니다. 예를 들어:
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)) // 会截取 4 ~ 1 这几个元素,返回一个新数组:[4,3,2,1]
}

여기에서 곰과 황소를 판단하는 조건은 다음과 같습니다.
self.numTick > 2이를 확립하려면 새로운 감지 가격이 발생할 때 처음부터 트리거되는 것을 피하기 위해 최소 3라운드의 감지 이후에 트리거되어야 함을 의미합니다.self.prices마지막 데이터는self.prices배열의 이전 범위에서 최대 또는 최소 가격의 차이가 깨져야 합니다.burstPrice이것은 폭발 가격입니다.모든 조건이 충족되면 표시하세요.bull또는bear,을 위한true, 그리고 주다tradeAmount변수를 할당하고 종마 거래를 계획합니다.
이전에 따르면self.updateTrades()함수에서 업데이트 및 계산됨self.vol, 매개변수에 대해BurstThresholdVol거래 강도를 줄일지(계획된 거래 규모를 줄일지) 결정합니다.
if (self.vol < BurstThresholdVol) {
tradeAmount *= self.vol / BurstThresholdVol // 缩减计划交易量,缩减为之前量的self.vol / BurstThresholdVol 倍
}
if (self.numTick < 5) {
tradeAmount *= 0.8 // 缩减为计划的80%
}
if (self.numTick < 10) { // 缩减为计划的80%
tradeAmount *= 0.8
}
다음으로, 거래 신호와 거래량이 요구 사항을 충족하는지 확인합니다.
if ((!bull && !bear) || tradeAmount < MinStock) { # 如果非牛市并且也非熊市,或者计划交易的量tradeAmount小于参数设置的最小交易量MinStock,poll函数直接返回,不做交易操作
return
}
위 판결 후 집행합니다var tradePrice = bull ? self.bidPrice : self.askPrice거래 가격을 하락장인지 상승장인지에 따라 설정하고, 해당 가치에 해당 운송장 가격을 할당합니다.
마지막으로 입력while루프를 멈추기 위한 유일한 조건은tradeAmount >= MinStock계획된 거래량이 최소 거래량보다 적습니다.
루프에서 주문은 현재 시장이 강세인지 약세인지에 따라 이루어집니다. 그리고 변수에 주문 ID를 기록합니다.orderId. 각 주문 라운드 후Sleep(200)200밀리초 동안 기다리세요. 그 다음에는 루프에서 판단하세요orderId조건이 참이면 참입니까(주문이 실패하면 주문 ID가 반환되지 않고 if 조건이 트리거되지 않음). 주문 ID를 가져와서 할당하세요self.tradeOrderId。
주문 데이터를 저장할 변수를 선언하세요order초기값은null. 그런 다음 루프를 실행하여 이 ID의 주문 데이터를 가져오고 주문이 보류 주문 상태인지 확인합니다. 보류 주문 상태인 경우 이 ID의 주문을 취소합니다. 보류 주문 상태가 아닌 경우 이 상태에서 점프합니다. 감지 루프.
var order = null // 声明一个变量用于保存订单数据
while (true) { // 一个while循环
order = exchange.GetOrder(orderId) // 调用GetOrder查询订单ID为 orderId的订单数据
if (order) { // 如果查询到订单数据,查询失败order为null,不会触发当前if条件
if (order.Status == ORDER_STATE_PENDING) { // 判断订单状态是不是正在挂单中
exchange.CancelOrder(orderId) // 如果当前正在挂单,取消该订单
Sleep(200)
} else { // 否则执行break跳出当前while循环
break
}
}
}
그런 다음 아래 과정을 따르세요.
self.tradeOrderId = 0 // 重置self.tradeOrderId
tradeAmount -= order.DealAmount // 更新tradeAmount,减去提单的订单已经成交的数量
tradeAmount *= 0.9 // 减小下单力度
if (order.Status == ORDER_STATE_CANCELED) { // 如果订单已经是取消了
self.updateOrderBook() // 更新订单薄等数据
while (bull && self.bidPrice - tradePrice > 0.1) { // 牛市时,更新后的提单价格超过当前交易价格0.1就减小交易力度,略微调整交易价格
tradeAmount *= 0.99
tradePrice += 0.1
}
while (bear && self.askPrice - tradePrice < -0.1) { // 熊市时,更新后的提单价格超过当前交易价格0.1就减小交易力度,略微调整交易价格
tradeAmount *= 0.99
tradePrice -= 0.1
}
}
프로그램 흐름이 튀어나올 때while (tradeAmount >= MinStock) {...}이 사이클은 가격 폭등 거래 과정이 완료되었음을 나타냅니다.
구현하다self.numTick = 0즉, 재설정self.numTick0입니다.
LeeksReaper()생성자가 마침내 실행됩니다self반환되는 객체는 다음과 같습니다.var reaper = LeeksReaper()반환되었을 때reaper。
지금까지LeeksReaper()우리는 생성자가 리크 하베스터 객체를 구성하는 방법, 리크 하베스터 객체의 다양한 메서드, 주요 논리 함수의 실행 프로세스를 분석했습니다. 이 글을 읽은 후에는 고주파수 함수에 대해 더 명확하게 이해하셨을 것이라고 생각합니다. 전략 알고리즘 프로세스를 이해하세요.