최근 발명가 양적화 微信 그룹 토론print money
이 로봇에 대한 논의는 매우 열렬했고, 아주 오래된 전략이 다시 광주시민들의 시야로 돌아왔다.print money
이 로봇 거래의 원리는 양배추 재배기 전략에 근거하여, 당시 양배추 재배기 전략에 대해 너무 잘 이해하지 못했고, 이해하지 못했다는 비난을 받았다. 그래서, 다시 원래의 전략을 진지하게 살펴보고 발명가의 양량화 된 이식 버전을 다시 보았습니다.OKCoin을 이식하는
[오케이코인 (OKCoin) 이식 콩나뭇가루 재배기] 전략 소스코드:
function LeeksReaper() {
var self = {}
self.numTick = 0
self.lastTradeId = 0
self.vol = 0
self.askPrice = 0
self.bidPrice = 0
self.orderBook = {Asks:[], Bids:[]}
self.prices = []
self.tradeOrderId = 0
self.p = 0.5
self.account = null
self.preCalc = 0
self.preNet = 0
self.updateTrades = function() {
var trades = _C(exchange.GetTrades)
if (self.prices.length == 0) {
while (trades.length == 0) {
trades = trades.concat(_C(exchange.GetTrades))
}
for (var i = 0; i < 15; i++) {
self.prices[i] = trades[trades.length - 1].Price
}
}
self.vol = 0.7 * self.vol + 0.3 * _.reduce(trades, function(mem, trade) {
// Huobi not support trade.Id
if ((trade.Id > self.lastTradeId) || (trade.Id == 0 && trade.Time > self.lastTradeId)) {
self.lastTradeId = Math.max(trade.Id == 0 ? trade.Time : trade.Id, self.lastTradeId)
mem += trade.Amount
}
return mem
}, 0)
}
self.updateOrderBook = function() {
var orderBook = _C(exchange.GetDepth)
self.orderBook = orderBook
if (orderBook.Bids.length < 3 || orderBook.Asks.length < 3) {
return
}
self.bidPrice = orderBook.Bids[0].Price * 0.618 + orderBook.Asks[0].Price * 0.382 + 0.01
self.askPrice = orderBook.Bids[0].Price * 0.382 + orderBook.Asks[0].Price * 0.618 - 0.01
self.prices.shift()
self.prices.push(_N((orderBook.Bids[0].Price + orderBook.Asks[0].Price) * 0.35 +
(orderBook.Bids[1].Price + orderBook.Asks[1].Price) * 0.1 +
(orderBook.Bids[2].Price + orderBook.Asks[2].Price) * 0.05))
}
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)
}
}
}
}
self.poll = function() {
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
if (self.account) {
LogStatus(self.account, 'Tick:', self.numTick, ', lastPrice:', self.prices[self.prices.length-1], ', burstPrice: ', burstPrice)
}
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
}
if (self.vol < BurstThresholdVol) {
tradeAmount *= self.vol / BurstThresholdVol
}
if (self.numTick < 5) {
tradeAmount *= 0.8
}
if (self.numTick < 10) {
tradeAmount *= 0.8
}
if ((!bull && !bear) || tradeAmount < MinStock) {
return
}
var tradePrice = bull ? self.bidPrice : self.askPrice
while (tradeAmount >= MinStock) {
var orderId = bull ? exchange.Buy(self.bidPrice, tradeAmount) : exchange.Sell(self.askPrice, tradeAmount)
Sleep(200)
if (orderId) {
self.tradeOrderId = orderId
var order = null
while (true) {
order = exchange.GetOrder(orderId)
if (order) {
if (order.Status == ORDER_STATE_PENDING) {
exchange.CancelOrder(orderId)
Sleep(200)
} else {
break
}
}
}
self.tradeOrderId = 0
tradeAmount -= order.DealAmount
tradeAmount *= 0.9
if (order.Status == ORDER_STATE_CANCELED) {
self.updateOrderBook()
while (bull && self.bidPrice - tradePrice > 0.1) {
tradeAmount *= 0.99
tradePrice += 0.1
}
while (bear && self.askPrice - tradePrice < -0.1) {
tradeAmount *= 0.99
tradePrice -= 0.1
}
}
}
}
self.numTick = 0
}
return self
}
function main() {
var reaper = LeeksReaper()
while (true) {
reaper.poll()
Sleep(TickInterval)
}
}
일반적으로 전략을 배우기 위해, 읽기 전에 전체 프로그램 구조를 살펴보십시오. 이 정책 코드는 200 줄 이하의 코드로 매우 가볍고 원본 버전의 정책 회화율이 높으며 기본적으로 동일한 것입니다.main()
함수가 실행되기 시작하면main()
그리고 그 중 하나는LeeksReaper()
이 함수들은LeeksReaper()
함수도 잘 이해되고 있는데, 이 함수는 콩 재배기 전략 논리 모듈 (즉, 하나의 객체) 의 구성 함수로 이해될 수 있으며, 간단히 말해서LeeksReaper()
그리고 그 중에서도 가장 중요한 것은,
키워드:
전략main
함수의 첫 줄:var reaper = LeeksReaper()
로컬 변수를 선언합니다.reaper
이 함수에서, 이 함수에서, 이 함수에서, 이 함수에서, 이 함수에서, 이 함수에서, 이 함수에서, 이 함수에서reaper
。
전략main
이 함수는 다음과 같습니다:
while (true) {
reaper.poll()
Sleep(TickInterval)
}
한 쪽으로while
죽음의 순환, 끊임없는 실행reaper
객체의 처리 함수poll()
,poll()
함수는 바로 거래 전략의 주요 논리이며, 전체 전략 절차는 끊임없이 실행되는 거래 논리를 시작합니다.
그리고Sleep(TickInterval)
이 라인은 통상 거래 논리가 실행된 후의 일시 중지 시간을 제어하기 위해 거래 논리의 회전 빈도를 제어하기 위해 이해된다.
LeeksReaper()
구성 함수보세요.LeeksReaper()
함수는 어떻게 전략 논리 객체를 구성합니까?
LeeksReaper()
이 함수는 시작해서 빈 객체를 선언합니다.var self = {}
그리고LeeksReaper()
함수 실행 과정에서 이 빈 객체에 몇 가지 방법, 속성을 추가하여 결국 이 객체의 구성을 완료하고 마지막으로 이 객체를 반환합니다.main()
함수 안쪽에 있는var reaper = LeeksReaper()
이 단계에서는 반환된 객체의 값을 부여합니다.reaper
)。
self
객체에 속성을 추가합니다다음으로self
많은 속성을 추가하고, 아래에서 각각의 속성을 설명하고, 속성, 변수의 용도, 의도, 전략을 쉽게 이해할 수 있도록 속성을 빠르게 이해할 수 있습니다.
self.numTick = 0 # 用来记录poll函数调用时未触发交易的次数,当触发下单并且下单逻辑执行完时,self.numTick重置为0
self.lastTradeId = 0 # 交易市场已经成交的订单交易记录ID,这个变量记录市场当前最新的成交记录ID
self.vol = 0 # 通过加权平均计算之后的市场每次考察时成交量参考(每次循环获取一次市场行情数据,可以理解为考察了行情一次)
self.askPrice = 0 # 卖单提单价格,可以理解为策略通过计算后将要挂卖单的价格
self.bidPrice = 0 # 买单提单价格
self.orderBook = {Asks:[], Bids:[]} # 记录当前获取的订单薄数据,即深度数据(卖一...卖n,买一...买n)
self.prices = [] # 一个数组,记录订单薄中前三档加权平均计算之后的时间序列上的价格,简单说就是每次储存计算得到的订单薄前三档加权平均价格,放在一个数组中,用于后续策略交易信号参考,所以该变量名是prices,复数形式,表示一组价格
self.tradeOrderId = 0 # 记录当前提单下单后的订单ID
self.p = 0.5 # 仓位比重,币的价值正好占总资产价值的一半时,该值为0.5,即平衡状态
self.account = null # 记录账户资产数据,由GetAccount()函数返回数据
self.preCalc = 0 # 记录最近一次计算收益时的时间戳,单位毫秒,用于控制收益计算部分代码触发执行的频率
self.preNet = 0 # 记录当前收益数值
self
객체를 추가하는 방법이 속성을 추가한 후,self
객체가 어떤 작업을 수행하고 어떤 기능을 갖도록 하는 방법을 추가합니다.
첫 번째 추가 함수:
self.updateTrades = function() {
var trades = _C(exchange.GetTrades) # 调用FMZ封装的接口GetTrades,获取当前最新的市场成交数据
if (self.prices.length == 0) { # 当self.prices.length == 0时,需要给self.prices数组填充数值,只有策略启动运行时才会触发
while (trades.length == 0) { # 如果近期市场上没有更新的成交记录,这个while循环会一直执行,直到有最新成交数据,更新trades变量
trades = trades.concat(_C(exchange.GetTrades)) # concat 是JS数组类型的一个方法,用来拼接两个数组,这里就是把“trades”数组和“_C(exchange.GetTrades)”返回的数组数据拼接成一个数组
}
for (var i = 0; i < 15; i++) { # 给self.prices填充数据,填充15个最新成交价格
self.prices[i] = trades[trades.length - 1].Price
}
}
self.vol = 0.7 * self.vol + 0.3 * _.reduce(trades, function(mem, trade) { # _.reduce 函数迭代计算,累计最新成交记录的成交量
// Huobi not support trade.Id
if ((trade.Id > self.lastTradeId) || (trade.Id == 0 && trade.Time > self.lastTradeId)) {
self.lastTradeId = Math.max(trade.Id == 0 ? trade.Time : trade.Id, self.lastTradeId)
mem += trade.Amount
}
return mem
}, 0)
}
updateTrades
이 함수의 역할은 최신의 시장 거래 데이터를 획득하고, 데이터에 따라 계산을 수행하고 기록하여 전략의 후속 논리에 사용할 수 있습니다.
이 글은 제가 직접 작성한 코드에서 나온다.
이 문제에 대해_.reduce
이 문서는 프로그래밍에 대한 기초가 없는 학생들이 혼란스러워할 수 있는 문장입니다._.reduce
그래요Underscore.js이 라이브러리의 함수, FMZJS 정책이 이 라이브러리를 지원하기 때문에 반복 계산은 매우 편리합니다.Underscore.js资料链接
이 글의 의미는 매우 간단합니다.
function main () {
var arr = [1, 2, 3, 4]
var sum = _.reduce(arr, function(ret, ele){
ret += ele
return ret
}, 0)
Log("sum:", sum) # sum 等于 10
}
이 수를 곱하면[1, 2, 3, 4]
이 숫자를 모두 더하면 됩니다.trades
대수열에 있는 각 거래 기록 데이터의 거래량 값이 더된다. 최신 거래 기록 거래량 총을 도출한다.self.vol = 0.7 * self.vol + 0.3 * _.reduce(...)
제가 사용하도록 허락해 주세요....
이 모든 코드들을 대체할 수 있습니다.self.vol
이 비율은 전략 작성자가 직접 설정한 것으로 시장 법칙을 관찰하는 것과 관련이 있을 수 있다.
만약 여러분이 제게 물어본다면, 만약 제가 최근에 거래된 데이터를 가져온 인터페이스가 제게 반복된 오래된 데이터를 돌려주면, 제가 얻은 데이터는 틀렸으며, 또 유용할 수 있을까요?
if ((trade.Id > self.lastTradeId) || (trade.Id == 0 && trade.Time > self.lastTradeId)) {
...
}
이 판단은 트랜잭션 기록의 트랜잭션 ID를 기준으로 판단할 수 있으며, ID가 이전 기록의 ID보다 크면만 누적을 유발하거나, 거래소 인터페이스가 ID를 제공하지 않으면, 즉,trade.Id == 0
거래 기록의 시간표를 사용하여,self.lastTradeId
트랜잭션 기록의 ID가 아닌 시간표가 저장됩니다.
두 번째 추가 함수:
self.updateOrderBook = function() {
var orderBook = _C(exchange.GetDepth)
self.orderBook = orderBook
if (orderBook.Bids.length < 3 || orderBook.Asks.length < 3) {
return
}
self.bidPrice = orderBook.Bids[0].Price * 0.618 + orderBook.Asks[0].Price * 0.382 + 0.01
self.askPrice = orderBook.Bids[0].Price * 0.382 + orderBook.Asks[0].Price * 0.618 - 0.01
self.prices.shift()
self.prices.push(_N((orderBook.Bids[0].Price + orderBook.Asks[0].Price) * 0.35 +
(orderBook.Bids[1].Price + orderBook.Asks[1].Price) * 0.1 +
(orderBook.Bids[2].Price + orderBook.Asks[2].Price) * 0.05))
}
다음으로updateOrderBook
이 함수는, 함수의 이름의 문자 그대로의 의미에서 볼 수 있듯이, 이 함수의 역할은 명령어 GetDepth()
현재 시장 주문 얇은 데이터를 얻습니다 (팔기 1... 팔기 n, 구매 1... 구매 n)self.orderBook
중. 다음으로, 주문 얇은 데이터 구매, 판매 주문 3 개 미만인 경우 무효 함수를 직접 반환합니다.
그 후 두 가지 자료를 계산했습니다.
요금 요금 계산 계산하는 청구서 가격은 또한 중량화 된 평균을 사용하여 계산됩니다. 지불금을 계산 할 때 구매 권리는 61.8% ((0.618), 판매 권리는 나머지 무게 38.2% ((0.382) 를 차지합니다. 송수신 판매 가격 계산에 있어서도 마찬가지이며, 판매권과 판매권에 비해 가격권이 더 크다. 0.618이 왜인지에 대해서는 저자가 금분할 비율을 선호하는 것일 수도 있다. 마지막에 추가한 점점값 (0.01) 을 빼는 것은 사서 중추에 조금 더 기울기 위해서다.
업데이트 시간 순서에서 주문 얇은 상위 3 계열 중량 평균 가격 주문이 적은 첫 3단계 구매, 판매권 가격의 가중화 평균 계산, 1단계 중량 0.7, 2단계 중량 0.2, 3단계 중량 0.1. 이 모든 것이 우리가 할 수 있는 일입니다.
(买一 + 卖一) * 0.35 + (买二 + 卖二) * 0.1 + (买三 + 卖三) * 0.05
->
(买一 + 卖一) / 2 * 2 * 0.35 + (买二 + 卖二) / 2 * 2 * 0.1 + (买三 + 卖三) / 2 * 2 * 0.05
->
(买一 + 卖一) / 2 * 0.7 + (买二 + 卖二) / 2 * 0.2 + (买三 + 卖三) / 2 * 0.1
->
第一档平均的价格 * 0.7 + 第二档平均的价格 * 0.2 + 第三档平均的价格 * 0.1
여기서 볼 수 있듯이, 최종 계산된 가격은 실제로 반현실 시장에서 상장된 3단계 중간에 있는 가격 위치입니다.
그리고 그 계산된 가격으로,self.prices
가장 오래된 데이터 (() 를 뽑아내기 위해shift()
함수), 최신 데이터에 대한 업데이트를 통해push()
함수, Shift, Push 함수는 JS 언어의 수직 객체의 방법이며, JS 자료를 검색하여 생성할 수 있습니다.)self.prices
대수열은 시간 순서 순서로 이루어진 데이터 스트림이다.
기침, 목수, 해부, 여기까지, 다음 시즌까지
나라는 점점 더 강해지고 있습니다.안녕하세요, 질문하고 싶습니다.self.prices 먼저 15개의 역사 거래 가격을 채우고, 다음으로 주문을 발급하기 전에 세 개의 중인 평균 가격을 채우십시오.
m0606불행히도, 많은 거래소에서 거래자들은 매매를 한 번 구매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 구매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 구매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 구매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 구매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번 판매 한 번
엄마감사합니다, 저는 파이썬 버전을
에디금분해 0.618 0.382는 사용된 피보 꿈의 총 소 떼
에반1987이 질문에 대한 답변은 매우 흥미롭습니다.
어서꿈의 총 소 p
9개의 태양꿈의 총, 소의 덩어리!
발명가들의 수량화 - 작은 꿈네, 그렇습니다.
발명가들의 수량화 - 작은 꿈이 모든 것은 주로 아이디어를 배우고, 이러한 높은 빈도의 거래 기회를 통찰하는 것입니다.
발명가들의 수량화 - 작은 꿈이 글은 라스본이 쓴 전략의 원리 분석에 대한 글을 읽을 수 있습니다. 높은 빈도 전략은 약간의 지원이 필요합니다.
발명가들의 수량화 - 작은 꿈감사합니다. 좋아하면 공유해 주세요.
발명가들의 수량화 - 작은 꿈감사합니다!
발명가들의 수량화 - 작은 꿈감사합니다!
발명가들의 수량화 - 작은 꿈감사합니다!
발명가들의 수량화 - 작은 꿈학창시절, 이 황금분할 비율을 배웠을 때 특히 잘 기억하고, 이 비율이 가장 아름다운 길고 넓은 정사각형이라고 말했다~~하지만 왜인지 모르겠습니다.
발명가들의 수량화 - 작은 꿈감사합니다.
발명가들의 수량화 - 작은 꿈사실 복잡하지 않습니다. 이 설명의 비교는 복잡합니다. 문장별로 가능한 한 이해하기 쉽게 설명합니다.