255 lines
6.3 KiB
Markdown
255 lines
6.3 KiB
Markdown
|
|
> Name
|
|
|
|
数字货币期货交易类库测试版
|
|
|
|
> Author
|
|
|
|
小小梦
|
|
|
|
> Strategy Description
|
|
|
|
## 数字货币期货交易类库(测试版)
|
|
|
|
- main函数为测试函数,调用例子
|
|
|
|
如有问题欢迎留言。
|
|
|
|
> Strategy Arguments
|
|
|
|
|
|
|
|
|Argument|Default|Description|
|
|
|----|----|----|
|
|
|Interval|500|失败重试间隔(毫秒)|
|
|
|MinAmount|true|最小交易数量|
|
|
|SlidePrice|5|下单滑价|
|
|
|
|
|
|
> Source (javascript)
|
|
|
|
``` javascript
|
|
// 参数
|
|
/*
|
|
var MinAmount = 1
|
|
var SlidePrice = 5
|
|
var Interval = 500
|
|
*/
|
|
|
|
function GetPosition(e, contractType, direction) {
|
|
e.SetContractType(contractType)
|
|
var positions = _C(e.GetPosition);
|
|
for (var i = 0; i < positions.length; i++) {
|
|
if (positions[i].ContractType == contractType && positions[i].Type == direction) {
|
|
return positions[i]
|
|
}
|
|
}
|
|
|
|
return null
|
|
}
|
|
|
|
function Open(e, contractType, direction, opAmount) {
|
|
var initPosition = GetPosition(e, contractType, direction);
|
|
var isFirst = true;
|
|
var initAmount = initPosition ? initPosition.Amount : 0;
|
|
var nowPosition = initPosition;
|
|
var directBreak = false
|
|
var preNeedOpen = 0
|
|
var timeoutCount = 0
|
|
while (true) {
|
|
var ticker = _C(e.GetTicker)
|
|
var needOpen = opAmount;
|
|
if (isFirst) {
|
|
isFirst = false;
|
|
} else {
|
|
nowPosition = GetPosition(e, contractType, direction);
|
|
if (nowPosition) {
|
|
needOpen = opAmount - (nowPosition.Amount - initAmount);
|
|
}
|
|
// 检测directBreak 并且持仓未变的情况
|
|
if (preNeedOpen == needOpen && directBreak) {
|
|
Log("疑似仓位数据延迟,等待30秒", "#FF0000")
|
|
Sleep(30000)
|
|
nowPosition = GetPosition(e, contractType, direction);
|
|
if (nowPosition) {
|
|
needOpen = opAmount - (nowPosition.Amount - initAmount);
|
|
}
|
|
/*
|
|
timeoutCount++
|
|
if (timeoutCount > 10) {
|
|
Log("连续10次疑似仓位延迟,下单失败!", "#FF0000")
|
|
break
|
|
}
|
|
*/
|
|
} else {
|
|
timeoutCount = 0
|
|
}
|
|
}
|
|
if (needOpen < MinAmount) {
|
|
break;
|
|
}
|
|
|
|
var amount = needOpen;
|
|
preNeedOpen = needOpen
|
|
e.SetDirection(direction == PD_LONG ? "buy" : "sell");
|
|
var orderId;
|
|
if (direction == PD_LONG) {
|
|
orderId = e.Buy(ticker.Sell + SlidePrice, amount, "开多仓", contractType, ticker);
|
|
} else {
|
|
orderId = e.Sell(ticker.Buy - SlidePrice, amount, "开空仓", contractType, ticker);
|
|
}
|
|
|
|
directBreak = false
|
|
var n = 0
|
|
while (true) {
|
|
Sleep(Interval);
|
|
var orders = _C(e.GetOrders);
|
|
if (orders.length == 0) {
|
|
if (n == 0) {
|
|
directBreak = true
|
|
}
|
|
break;
|
|
}
|
|
for (var j = 0; j < orders.length; j++) {
|
|
e.CancelOrder(orders[j].Id);
|
|
if (j < (orders.length - 1)) {
|
|
Sleep(Interval);
|
|
}
|
|
}
|
|
n++
|
|
}
|
|
}
|
|
|
|
var ret = {
|
|
price: 0,
|
|
amount: 0,
|
|
position: nowPosition
|
|
};
|
|
if (!nowPosition) {
|
|
return ret;
|
|
}
|
|
if (!initPosition) {
|
|
ret.price = nowPosition.Price;
|
|
ret.amount = nowPosition.Amount;
|
|
} else {
|
|
ret.amount = nowPosition.Amount - initPosition.Amount;
|
|
ret.price = _N(((nowPosition.Price * nowPosition.Amount) - (initPosition.Price * initPosition.Amount)) / ret.amount);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
function Cover(e, contractType, opAmount, direction) {
|
|
var initPosition = null;
|
|
var position = null;
|
|
var isFirst = true;
|
|
|
|
while (true) {
|
|
while (true) {
|
|
Sleep(Interval);
|
|
var orders = _C(e.GetOrders);
|
|
if (orders.length == 0) {
|
|
break;
|
|
}
|
|
for (var j = 0; j < orders.length; j++) {
|
|
e.CancelOrder(orders[j].Id);
|
|
if (j < (orders.length - 1)) {
|
|
Sleep(Interval);
|
|
}
|
|
}
|
|
}
|
|
|
|
position = GetPosition(e, contractType, direction)
|
|
if (!position) {
|
|
break
|
|
}
|
|
if (isFirst == true) {
|
|
initPosition = position;
|
|
opAmount = Math.min(opAmount, initPosition.Amount)
|
|
isFirst = false;
|
|
}
|
|
|
|
var amount = opAmount - (initPosition.Amount - position.Amount)
|
|
if (amount <= 0) {
|
|
break
|
|
}
|
|
|
|
var ticker = _C(e.GetTicker)
|
|
if (position.Type == PD_LONG) {
|
|
e.SetDirection("closebuy");
|
|
e.Sell(ticker.Buy - SlidePrice, amount, "平多仓", contractType, ticker);
|
|
} else if (position.Type == PD_SHORT) {
|
|
e.SetDirection("closesell");
|
|
e.Buy(ticker.Sell + SlidePrice, amount, "平空仓", contractType, ticker);
|
|
}
|
|
|
|
Sleep(Interval)
|
|
}
|
|
|
|
return position
|
|
}
|
|
|
|
$.OpenLong = function(e, contractType, amount) {
|
|
if (typeof(e) == "string") {
|
|
amount = contractType
|
|
contractType = e
|
|
e = exchange
|
|
}
|
|
|
|
return Open(e, contractType, PD_LONG, amount);
|
|
}
|
|
|
|
$.OpenShort = function(e, contractType, amount) {
|
|
if (typeof(e) == "string") {
|
|
amount = contractType
|
|
contractType = e
|
|
e = exchange
|
|
}
|
|
|
|
return Open(e, contractType, PD_SHORT, amount);
|
|
};
|
|
|
|
$.CoverLong = function(e, contractType, amount) {
|
|
if (typeof(e) == "string") {
|
|
amount = contractType
|
|
contractType = e
|
|
e = exchange
|
|
}
|
|
|
|
return Cover(e, contractType, amount, PD_LONG);
|
|
};
|
|
|
|
$.CoverShort = function(e, contractType, amount) {
|
|
if (typeof(e) == "string") {
|
|
amount = contractType
|
|
contractType = e
|
|
e = exchange
|
|
}
|
|
|
|
return Cover(e, contractType, amount, PD_SHORT);
|
|
};
|
|
|
|
|
|
function main() {
|
|
Log(exchange.GetPosition())
|
|
var info = $.OpenLong(exchange, "quarter", 100)
|
|
Log(info, "#FF0000")
|
|
|
|
Log(exchange.GetPosition())
|
|
info = $.CoverLong(exchange, "quarter", 30)
|
|
Log(exchange.GetPosition())
|
|
Log(info, "#FF0000")
|
|
|
|
info = $.CoverLong(exchange, "quarter", 80)
|
|
Log(exchange.GetPosition())
|
|
Log(info, "#FF0000")
|
|
}
|
|
```
|
|
|
|
> Detail
|
|
|
|
https://www.fmz.com/strategy/203258
|
|
|
|
> Last Modified
|
|
|
|
2022-01-07 09:42:47
|