This commit is contained in:
botvs
2017-02-16 09:41:36 +08:00
parent d9e70db63a
commit 82b672e719
4 changed files with 55 additions and 36 deletions
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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 ||