-
Notifications
You must be signed in to change notification settings - Fork 7
/
BTC期货交易类库限价单代码分析.js
213 lines (203 loc) · 10.8 KB
/
BTC期货交易类库限价单代码分析.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
// botvs@43a2f76fd07903640a0f22187ef624aa
function GetPosition(e, contractType, direction) {//获取持仓信息,供 开仓 平仓 函数 使用
var allCost = 0;
var allAmount = 0;
var allProfit = 0;
var allFrozen = 0;
var posMargin = 0;//持仓 杠杆
var positions = _C(e.GetPosition);//调用API 获取持仓信息
for (var i = 0; i < positions.length; i++) {//遍历持仓信息 的 数组
if ( positions[i].ContractType == contractType &&
//合约类型相同 且
(((positions[i].Type == PD_LONG ) && direction == PD_LONG) || ((positions[i].Type == PD_SHORT) && direction == PD_SHORT))
//修改
) {//执行以下
posMargin = positions[i].MarginLevel; //获取持仓合约 杠杆
allCost += (positions[i].Price * positions[i].Amount); //累计所有符合条件的 合约的总金额
allAmount += positions[i].Amount;//累计所有符合条件的合约的 量
allProfit += positions[i].Profit;//累计所有符合条件的合约的 浮动盈亏
allFrozen += positions[i].FrozenAmount;//累计所有符合条件的合约的 冻结量
}
}
if (allAmount === 0) {//如果没有符合条件的 合约
return null;//返回 null
}
return {//返回一个对象
MarginLevel: posMargin,//杠杆
FrozenAmount: allFrozen,//所有冻结
Price: _N(allCost / allAmount),//所有该类型合约 持仓的均价
Amount: allAmount, //持仓量
Profit: allProfit,//总盈亏
Type: direction,// 方向
ContractType: contractType//持仓方向
};
}
var step = 0.5; //增量
function Open(e, contractType, direction, opAmount ,price) {//开仓函数,参数:交易所,合约类型,方向,数量
var initPosition = GetPosition(e, contractType, direction);//获取持仓信息,记录在 初始 持仓对象
var isFirst = true;//首次标记
var initAmount = initPosition ? initPosition.Amount : 0;//有持仓信息 获取持仓数量 , 没有 就赋值0
var positionNow = initPosition;//initPosition更新给 positionNow
while (true) {//循环
//Sleep(60000); //ceshi
var needOpen = opAmount;//把操作量 赋值给 needOpen
if (isFirst) {//第一次啥都不做
isFirst = false;//更新 标记
} else {
positionNow = GetPosition(e,contractType, direction);//获取当前持仓信息
if (positionNow) {//如果有持仓信息
needOpen = opAmount - (positionNow.Amount - initAmount);
//接下来需要开仓的量 = 操作量 - 已新开仓的量
}
}
var isSetSuccess = _C(e.SetContractType, contractType); //数字货币 期货 返回 false 或者 true
if(isSetSuccess === false){
throw 'SetContractType is return false';
}
if (needOpen < e.GetMinStock()) {//如果 需要加仓的量 小于 该合约 允许的最小量
break;//跳出循环
}
var depth = _C(e.GetDepth);//获取深度
var amount = needOpen;//amount最大 不超过GetMinStock
e.SetDirection(direction == PD_LONG ? "buy" : "sell");//设置下单类型, 方向为多头 则开多仓 ,否则 开空仓
var orderId;//订单ID
if (direction == PD_LONG) {//如果方向 是多头
orderId = e.Buy( (typeof(price) == 'undefined' ? depth.Asks[0].Price + SlidePrice : Math.min(depth.Asks[0].Price + SlidePrice, price) ), amount, "开多仓",contractType, 'Ask', depth.Asks[0]);
Log("持仓:",_C(e.GetPosition,contractType));//ceshi
//开多仓 , 卖单数组索引0元素的价格 + 滑价 交易量 不大于 索引0元素的卖单量 输出的信息: 合约类型 市场深度单
} else {
orderId = e.Sell( (typeof(price) == 'undefined' ? depth.Bids[0].Price - SlidePrice : Math.max(depth.Bids[0].Price - SlidePrice, price) ), amount, "开空仓",contractType, 'Bid', depth.Bids[0]);
Log("持仓:",_C(e.GetPosition,contractType));//ceshi
//开空仓同上
}
// CancelPendingOrders
while (true) {
//Sleep(60000); //ceshi
var orders = _C(e.GetOrders);//获取 所有 未完成的 订单
if (orders.length === 0) {//如果 未完成的 订单数组 长度为0 ,则 表示 没有未完成的 订单
break; //跳出 while 循环
}
Sleep(Interval);//轮询间隔
for (var j = 0; j < orders.length; j++) {//遍历 未完成的订单 数组
e.CancelOrder(orders[j].Id);// 取消订单
if (j < (orders.length - 1)) {//作用 减少一次 轮询 提升效率
Sleep(Interval);
}
}
}
if(direction == PD_LONG){
price = price + step;
}else if(direction == PD_SHORT){
price = price - step;
}
}
var ret = { //返回的 对象
price: 0, //本次开仓均价
amount: 0, //本次新增持仓量
position: positionNow //持仓信息
};
if (!positionNow) {//持仓信息为null ,直接返回 ret 这种情况:没有开仓成功 返回 未修改的ret
return ret;
}
if (!initPosition) {//如果 初始 持仓信息 为null 这种情况: 开仓前 没有持仓, 更新ret 此刻持仓 为 新开仓信息
ret.price = positionNow.Price; //用此刻持仓信息 赋值
ret.amount = positionNow.Amount;
} else {//这种情况: 开始有持仓, 加仓成功
ret.amount = positionNow.Amount - initPosition.Amount;//算出新加仓的量
ret.price = _N(((positionNow.Price * positionNow.Amount) - (initPosition.Price * initPosition.Amount)) / ret.amount);//算出新加仓的均价
}
return ret;//返回 ret
}
function Cover(e, contractType ,price) {//平仓函数
var isSetSuccess = _C(e.SetContractType, contractType);//设置合约类型 获取合约详细信息
if(isSetSuccess === false){
throw 'SetContractType is return false';
}
while (true) {//循环
//Sleep(60000); //ceshi
var n = 0;
var positions = _C(e.GetPosition);//获取持仓信息
for (var i = 0; i < positions.length; i++) {//遍历持仓
if (positions[i].ContractType != contractType) {//如果 不是 要平仓的 合约类型 跳过 继续找
continue;
}
var amount = positions[i].Amount;
var depth;//声明 市场深度
if (positions[i].Type == PD_LONG ) {//如果持仓类型为多头
depth = _C(e.GetDepth);//获取市场深度
e.SetDirection("closebuy");
//设置 下单类型
e.Sell(depth.Bids[0].Price - SlidePrice, Math.min(amount, depth.Bids[0].Amount), contractType,"平多仓--","Bid", depth.Bids[0]);
//平多仓操作 , 跟随 输出一些信息
n++;//执行平仓计数累计
} else if (positions[i].Type == PD_SHORT) {
//如果是 空头 仓位
depth = _C(e.GetDepth);//获取市场深度
e.SetDirection("closesell");
//设置 下单类型
e.Buy(depth.Asks[0].Price + SlidePrice, Math.min(amount, depth.Asks[0].Amount), contractType,"平空仓--", 'Ask', depth.Asks[0]);
//平空仓操作,
n++;//执行平仓计数累计
}
}
if (n === 0) {//当计数 为初始 且 不变 ,证明 没有平仓操作进行,平仓完成
break;//跳出 while
}
Sleep(Interval);//轮询间隔
}
Log("持仓:",_C(e.GetPosition,contractType));//ceshi
}
//PositionManager对象的 构造函数
var PositionManager = (function() {// (一个匿名函数)(); ==> 立即执行 例如:function a(){alert("我是函数!")} ,声明后立即执行 a();一样
//返回PositionManager 函数 给 构造函数
function PositionManager(e) {//闭包, 初始化?
if (typeof(e) === 'undefined') {//参数e没有 传递进来的值 执行以下
e = exchange;//把 交易所对象赋值给e
}
if (e.GetName() !== 'Futures_OKCoin') {//交易所 不是CTP期货 则
throw 'Only support Futures_OKCoin';//抛出 错误信息
}
this.e = e;// 把e 赋值给 var PositionManager = (function() { , var 后的 PositionManager函数对象
this.account = null;// 同上
}
PositionManager.prototype.GetAccount = function() {//prototype是每个函数对象都有的属性,它指向函数原型的引用,
//如果 函数为构造函数,即PositionManager用作构造函数,那么 新生成的对象 会继承prototype 的属性
return _C(this.e.GetAccount);//本函数 给prototype 添加了一个属性函数 GetAccount 函数,获取交易所账户信息
};
PositionManager.prototype.OpenLong = function(contractType, shares ,price) {//同上,开多仓,参数 合约类型(类似商品名称),份数
if (!this.account) {//如果账户信息 不存在 null
this.account = _C(exchange.GetAccount); //获取全局 对象 交易所对象的账户信息
}
return Open(this.e, contractType, PD_LONG, shares, price);//调用上面的 Open函数 处理开多仓。
};
PositionManager.prototype.OpenShort = function(contractType, shares ,price) {//类似上面,
if (!this.account) {
this.account = _C(exchange.GetAccount);
}
return Open(this.e, contractType, PD_SHORT, shares, price);//调用Open函数 处理开空仓
};
PositionManager.prototype.Cover = function(contractType, price) {//平仓
if (!this.account) {
this.account = _C(exchange.GetAccount);
}
return Cover(this.e, contractType ,price);//调用平仓函数
};
PositionManager.prototype.Profit = function(contractType) {//计算 盈亏
var accountNow = _C(this.e.GetAccount);//获取此刻账户信息
Log("NOW:",accountNow,"--account:",this.account);
return _N(accountNow.Balance - this.account.Balance);//计算盈亏并返回,第一次初始时account为null,不管开仓平仓,会获取一下 账户信息
};
return PositionManager;//返回函数对象
})();
//导出的函数 生成一个 新的 交易管理对象
$.NewPositionManager = function(e) {//JS声明函数的 一种方法,先声明后执行
return new PositionManager(e);//返回 由PositionManager构造函数 生成的新对象
};
//测试
function main() {//测试 函数
var p = $.NewPositionManager();
p.OpenShort("week", 10,2890);
Sleep(500);
p.Cover("week");
LogProfit(p.Profit());
}