update
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
|
||||
|
||||
- [移植 OKCoin 韭菜收割机](https://www.botvs.com/strategy/34388)
|
||||
- [商品期货交易类库](https://www.botvs.com/strategy/12961)
|
||||
- [商品期货套利 - 多品种网格对冲模型](https://www.botvs.com/strategy/27799)
|
||||
- [比特币现货阶梯差价对冲](https://www.botvs.com/strategy/30573)
|
||||
- [策略框架模板](https://www.botvs.com/strategy/30861)
|
||||
@@ -19,7 +20,6 @@
|
||||
- [商品期货跨期对冲 - 单品种套利合约](https://www.botvs.com/strategy/27122)
|
||||
- [python版CTP商品期货交易类库](https://www.botvs.com/strategy/24288)
|
||||
- [Python API 测试](https://www.botvs.com/strategy/21365)
|
||||
- [商品期货交易类库](https://www.botvs.com/strategy/12961)
|
||||
- [从第三方获取K线 (商品期货版) Rev. 161216](https://www.botvs.com/strategy/15498)
|
||||
- [均线策略 30 行搞定](https://www.botvs.com/strategy/12348)
|
||||
- [商品期货跨期对冲 - 百行代码实现](https://www.botvs.com/strategy/23896)
|
||||
|
||||
+28
-15
@@ -33,21 +33,27 @@ function main() {
|
||||
`不断完善中...`
|
||||
|
||||
|
||||
参数 默认值 描述
|
||||
----------- ----- -----------
|
||||
Interval 500 失败重试间隔(毫秒)
|
||||
SlideTick true 滑价点数(整数)
|
||||
RiskControl false 开启风控
|
||||
MaxTrade 50 工作日最多交易交易次数
|
||||
参数 默认值 描述
|
||||
-------------- ----- -----------
|
||||
Interval 500 失败重试间隔(毫秒)
|
||||
SlideTick true 滑价点数(整数)
|
||||
RiskControl false 开启风控
|
||||
MaxTrade 50 工作日最多交易交易次数
|
||||
MaxTradeAmount 1000 单笔最多下单量
|
||||
*/
|
||||
|
||||
var __orderCount = 0
|
||||
var __orderDay = 0
|
||||
|
||||
function CanTrade() {
|
||||
function CanTrade(tradeAmount) {
|
||||
if (!RiskControl) {
|
||||
return true
|
||||
}
|
||||
if (typeof(tradeAmount) == 'number' && tradeAmount > MaxTradeAmount) {
|
||||
Log("风控模块限制, 超过最大下单量", MaxTradeAmount, "#ff0000 @");
|
||||
throw "中断执行"
|
||||
return false;
|
||||
}
|
||||
var nowDay = new Date().getDate();
|
||||
if (nowDay != __orderDay) {
|
||||
__orderDay = nowDay;
|
||||
@@ -55,7 +61,7 @@ function CanTrade() {
|
||||
}
|
||||
__orderCount++;
|
||||
if (__orderCount > MaxTrade) {
|
||||
Log("风控模块限制, 不可交易, 超过最大下单量", MaxTrade, "#ff0000 @");
|
||||
Log("风控模块限制, 不可交易, 超过最大下单次数", MaxTrade, "#ff0000 @");
|
||||
throw "中断执行"
|
||||
return false;
|
||||
}
|
||||
@@ -126,7 +132,7 @@ function Open(e, contractType, direction, opAmount) {
|
||||
if (needOpen < insDetail.MinLimitOrderVolume) {
|
||||
break;
|
||||
}
|
||||
if (!CanTrade()) {
|
||||
if (!CanTrade(opAmount)) {
|
||||
break;
|
||||
}
|
||||
var depth = _C(e.GetDepth);
|
||||
@@ -172,12 +178,10 @@ function Open(e, contractType, direction, opAmount) {
|
||||
}
|
||||
|
||||
function Cover(e, contractType) {
|
||||
if (!CanTrade()) {
|
||||
return;
|
||||
}
|
||||
var insDetail = _C(e.SetContractType, contractType);
|
||||
while (true) {
|
||||
var n = 0;
|
||||
var opAmount = 0;
|
||||
var positions = _C(e.GetPosition);
|
||||
for (var i = 0; i < positions.length; i++) {
|
||||
if (positions[i].ContractType != contractType) {
|
||||
@@ -187,13 +191,22 @@ function Cover(e, contractType) {
|
||||
var depth;
|
||||
if (positions[i].Type == PD_LONG || positions[i].Type == PD_LONG_YD) {
|
||||
depth = _C(e.GetDepth);
|
||||
opAmount = Math.min(amount, depth.Bids[0].Amount);
|
||||
if (!CanTrade(opAmount)) {
|
||||
return;
|
||||
}
|
||||
e.SetDirection(positions[i].Type == PD_LONG ? "closebuy_today" : "closebuy");
|
||||
e.Sell(depth.Bids[0].Price - (insDetail.PriceTick * SlideTick), Math.min(amount, depth.Bids[0].Amount), contractType, positions[i].Type == PD_LONG ? "平今" : "平昨", 'Bid', depth.Bids[0]);
|
||||
|
||||
e.Sell(depth.Bids[0].Price - (insDetail.PriceTick * SlideTick), opAmount, contractType, positions[i].Type == PD_LONG ? "平今" : "平昨", 'Bid', depth.Bids[0]);
|
||||
n++;
|
||||
} else if (positions[i].Type == PD_SHORT || positions[i].Type == PD_SHORT_YD) {
|
||||
depth = _C(e.GetDepth);
|
||||
opAmount = Math.min(amount, depth.Asks[0].Amount);
|
||||
if (!CanTrade(opAmount)) {
|
||||
return;
|
||||
}
|
||||
e.SetDirection(positions[i].Type == PD_SHORT ? "closesell_today" : "closesell");
|
||||
e.Buy(depth.Asks[0].Price + (insDetail.PriceTick * SlideTick), Math.min(amount, depth.Asks[0].Amount), contractType, positions[i].Type == PD_SHORT ? "平今" : "平昨", 'Ask', depth.Asks[0]);
|
||||
e.Buy(depth.Asks[0].Price + (insDetail.PriceTick * SlideTick), opAmount, contractType, positions[i].Type == PD_SHORT ? "平今" : "平昨", 'Ask', depth.Asks[0]);
|
||||
n++;
|
||||
}
|
||||
}
|
||||
@@ -554,7 +567,7 @@ $.NewTaskQueue = function(onTaskFinish) {
|
||||
if (self.cancelAll(task.e) != self.ERR_SUCCESS) {
|
||||
return self.ERR_TRADE;
|
||||
}
|
||||
if (!CanTrade()) {
|
||||
if (!CanTrade(task.amount)) {
|
||||
ret = null
|
||||
break
|
||||
}
|
||||
|
||||
@@ -58,8 +58,9 @@ function Hedge(q, e, positions, symbolA, symbolB, hedgeSpread) {
|
||||
hold: 0
|
||||
}
|
||||
if (n > 0) {
|
||||
n -= Math.min(n, st.amount)
|
||||
st.hold = st.amount * coefficient
|
||||
var m = Math.min(n, st.amount)
|
||||
n -= m
|
||||
st.hold = m * coefficient
|
||||
Log("恢复", self.name, st)
|
||||
}
|
||||
self.dic.push(st)
|
||||
|
||||
+23
-18
@@ -6,7 +6,7 @@
|
||||
|
||||
移植自: https://github.com/richox/okcoin-leeks-reaper
|
||||
|
||||
原作者说收手续费以后就失效了, 我只做了移植(支持Huobi), 没有实盘测试, 有兴趣可以学习
|
||||
原作者说收手续费以后就失效了, 我只做了移植, 没有实盘测试, 有兴趣可以学习
|
||||
因为策略使用了GetTrades 这个函数在回测系统中是被模拟出来的, 所以回测没有什么意义, 只能直接上实盘测试 !
|
||||
|
||||
以下为原说明
|
||||
@@ -38,13 +38,14 @@ OKCoin韭菜收割机
|
||||
BTC: 3QFn1qfZMhMQ4FhgENR7fha3T8ZVw1bEeU
|
||||
|
||||
|
||||
参数 默认值 描述
|
||||
----------------- ------- -------------------
|
||||
BurstThresholdPct 5e-05 burst.threshold.pct
|
||||
BurstThresholdVol 10 burst.threshold.vol
|
||||
MinStock 0.1 最小交易量
|
||||
CalcNetInterval 60 净值计算周期(秒)
|
||||
TickInterval 280 轮训周期(毫秒)
|
||||
参数 默认值 描述
|
||||
----------------- --------- -------------------
|
||||
BurstThresholdPct 5e-05 burst.threshold.pct
|
||||
BurstThresholdVol 10 burst.threshold.vol
|
||||
MinStock 0.1 最小交易量
|
||||
CalcNetInterval 60 净值计算周期(秒)
|
||||
BalanceTimeout 10000 平衡等代时间(毫秒)
|
||||
TickInterval 280 轮训周期(毫秒)
|
||||
*/
|
||||
|
||||
function LeeksReaper() {
|
||||
@@ -58,6 +59,7 @@ function LeeksReaper() {
|
||||
self.prices = []
|
||||
self.tradeOrderId = 0
|
||||
self.p = 0.5
|
||||
self.account = null
|
||||
self.preCalc = 0
|
||||
self.preNet = 0
|
||||
|
||||
@@ -99,6 +101,7 @@ function LeeksReaper() {
|
||||
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
|
||||
@@ -108,30 +111,29 @@ function LeeksReaper() {
|
||||
LogProfit(net)
|
||||
}
|
||||
}
|
||||
LogStatus(account, '\n', self.prices)
|
||||
self.btc = account.Stocks
|
||||
self.cny = account.Balance
|
||||
self.p = self.btc * self.prices[self.prices-1] / (self.btc * self.prices[self.prices-1] + self.cny)
|
||||
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] + 0.00, 0.01)
|
||||
exchange.Buy(self.orderBook.Bids[0] + 0.01, 0.01)
|
||||
exchange.Buy(self.orderBook.Bids[0] + 0.02, 0.01)
|
||||
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.Bids.length >0) {
|
||||
exchange.Sell(self.orderBook.Asks[0] - 0.00, 0.01)
|
||||
exchange.Sell(self.orderBook.Asks[0] - 0.01, 0.01)
|
||||
exchange.Sell(self.orderBook.Asks[0] - 0.02, 0.01)
|
||||
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(400)
|
||||
Sleep(BalanceTimeout)
|
||||
var orders = exchange.GetOrders()
|
||||
if (orders) {
|
||||
for (var i = 0; i < orders.length; i++) {
|
||||
@@ -152,6 +154,9 @@ function LeeksReaper() {
|
||||
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 ||
|
||||
|
||||
Reference in New Issue
Block a user