forked from fmzquant/strategies
-
Notifications
You must be signed in to change notification settings - Fork 1
/
价值比例法.js
250 lines (208 loc) · 7.22 KB
/
价值比例法.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
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
/*
策略出处: https://www.botvs.com/strategy/9784
策略名称: 价值比例法
策略作者: Lizza
策略描述:
设定一个用于投资的资金额度,如1000元。设定一个资金和比特币的价值比例,如50:50。根据现价,一直维持资金和比特币的价值比例。
如初始资金10000元,设定资金和比特币的比例为30:70,在第一次交易时买入7000元比特币(假设币价为1000元,买入7个币),剩余资金为3000元,保持比例为30:70。
下一个交易周期,假设币价变为1500元,则总价值变为1500*7 + 3000= 13500,则应保持手中资金为13500*0.3 = 4050元,则应卖出4050 - 3000 = 1050的比特币,卖出数量为1050/1500 = 0.7个,手中剩余比特币7-0.7=6.3个,币价值为6.3*1500 = 9450。 资金与比特币价值比例为4050:9450 = 30:70。
同理,币价下跌时则买入以保持比例不变。
参数 默认值 描述
-------------- ----- ---------
UseAccount true 使用帐户内全部资金
InitMoney 1000 初始资金量。
InitStock 3 初始币数。
StockRatio 0.5 币价值占总价值比例
InvestInterval true 投资间隔。
ErrorInterval 300 出错重试间隔。
SlidePrice 0.01 滑点
*/
var initAccount = null;
var initPrice = 0;
var stockHold = 0;
var moneyHold = 0;
var lastOrderID = null;
var prices = [];
function AdjustFloat(v) {
return Math.floor(v * 1000)/1000;
}
function GetAccount() {
var account = null;
while (!(account = exchange.GetAccount())) {
Log('Get Account Error');
Sleep(ErrorInterval);
}
return account;
}
function GetCurrentPrice() {
var ticker = null;
while (!(ticker = exchange.GetTicker())) {
Log('Get Ticker Error');
Sleep(ErrorInterval);
}
return AdjustFloat(ticker.Last);
}
function GetOrders(){
var orders = null;
while (!(orders = exchange.GetOrders())) {
Log('Get Orders Error');
Sleep(ErrorInterval);
}
return orders;
}
function CancelPendingOrders() {
while(true){
var orders = GetOrders();
if (orders.length === 0) {
return;
}
for (var i = 0; i < orders.length; i++) {
exchange.CancelOrder(orders[i].Id);
if (i < (orders.length-1)) {
Sleep(ErrorInterval);
}
}
}
}
function GetStatus(){
var price = GetCurrentPrice();
var initStockValue = InitStock + InitMoney/initPrice;
var initMoneyValue = InitMoney + InitStock * initPrice;
var stockValueNow = stockHold + moneyHold/price;
var moneyValueNow = stockHold * price + moneyHold;
var stockEarned = stockValueNow - initStockValue;
var moneyEarned = moneyValueNow - initMoneyValue;
var averagePrice = 0;
var alpha = (stockHold - InitStock)*(price - initPrice);
var beta = moneyEarned - alpha;
var sum = 0;
if(prices.length > 0){
for (var i = prices.length - 1; i >= 0; i--) {
sum += prices[i];
}
averagePrice = sum / prices.length;
}
var logString = 'Stock Holding:' + AdjustFloat(stockHold) + '\n';
logString += 'Money Holding:' + AdjustFloat(moneyHold) + '\n';
logString += 'Stock Earned:' + AdjustFloat(stockEarned) + '\n';
logString += 'Money Earned:' + AdjustFloat(moneyEarned)+ '\n';
logString += 'History Average price:' + averagePrice +'\n';
logString += 'Current Price:' + price +'\n';
logString += 'Alpha:' + alpha + '\n';
logString += 'Beta:' + beta;
LogProfit(moneyEarned);
return logString;
}
function CaculateHoldings(){
CancelPendingOrders();
if(lastOrderID){
var order = exchange.GetOrder(lastOrderID);
Log('last order:',order);
if(order.Status === ORDER_STATE_CLOSED){
if(order.Type === ORDER_TYPE_BUY){//Buy
stockHold += order.DealAmount;
moneyHold -= order.DealAmount * order.Price;
Log("Order Buy. stockHold +=:", order.DealAmount, ',Money -=:', order.DealAmount * order.Price);
}
else{ //Sell
stockHold -= order.DealAmount;
moneyHold += order.DealAmount * order.Price;
Log("Order Sell. stockHold -=:", order.DealAmount, ',Money +=:', order.DealAmount * order.Price);
}
}
}
}
function OnTick(){
var currentPrice = GetCurrentPrice();
prices.push(currentPrice);
//Log('History prices:',prices);
var stockValue = 0;
var totalValue = 0;
var ratio = 0;
stockValue = stockHold * currentPrice;
totalValue = stockValue + moneyHold;
ratio = stockValue / totalValue;
Log('Current Price:',currentPrice);
Log('stockHold:', stockHold);
Log('moneyHold:', moneyHold);
Log('stockValue:',stockValue);
Log('Current Ratio:', ratio);
if(ratio > StockRatio){ //Sell
Log('Current ratio > StockRatio');
var sellAmt = (stockValue - totalValue*StockRatio)/(currentPrice - SlidePrice);
lastOrderID = exchange.Sell(currentPrice - SlidePrice, sellAmt);
}else{ //Buy
Log('Current ratio < StockRatio');
var buyAmt = (totalValue*StockRatio - stockValue)/(currentPrice + SlidePrice);
lastOrderID = exchange.Buy(currentPrice + SlidePrice, buyAmt);
}
Log('Order ID:',lastOrderID);
CaculateHoldings();
}
function main() {
if(InitStock < 0) {
Log('Stock less than zero.');
return;
}
if(InitMoney < 0){
Log('Money less than zero.');
}
//if(InvestInterval < 0){
// Log('InvestInterval less than zero.');
//}
if(ErrorInterval < 0){
Log('ErrorInterval less than zero.');
}
if(StockRatio < 0 || StockRatio > 1){
Log('StockRatio should be a number from 0 to 1.');
}
EnableLogLocal(true);
SetFailover(true);
exchange.IO("websocket");
Log(exchange.GetName(), exchange.GetCurrency());
initAccount = _G('InitAccount');
if(initAccount === null){
initAccount = GetAccount();
_G('InitAccount',initAccount);
}
Log('InitAccount',initAccount);
initPrice = _G('InitPrice');
if(initPrice === null){
initPrice = GetCurrentPrice();
_G('InitPrice',initPrice);
}
Log('InitPrice',initPrice);
if(UseAccount){
InitMoney = initAccount.Balance + initAccount.FrozenBalance;
InitStock = initAccount.Stocks + initAccount.FrozenStocks;
}
Log('InitMoney:',InitMoney);
Log('InitStock:',InitStock);
stockHold = _G('StockHold');
if(stockHold === null){
stockHold = InitStock;
Log('Set Stock Hold',stockHold);
}
moneyHold = _G('MoneyHold');
if(moneyHold === null){
moneyHold = InitMoney;
Log('Set Money Hold',moneyHold);
}
if(_G('Prices') !== null){
prices = _G('Prices');
}
while (true) {
OnTick();
LogStatus(GetStatus());
Sleep(InvestInterval * 1000 * 60);
}
}
function onexit(){
_G('StockHold',stockHold);
_G('MoneyHold',moneyHold);
//_G('Prices',prices);
Log('Set Stock Hold',stockHold);
Log('Set Money Hold',moneyHold);
Log('Set prices:',prices);
Log('Robot Stopped!#ff0000@');
}