kraken-grid 1.4.5 → 1.4.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +72 -66
- package/TFCtest/lastFile.txt +1 -0
- package/allocation.ts +4 -0
- package/balancer.ts +8 -7
- package/bot.ts +44 -18
- package/dist/TFCtest/callCache.json +2163 -0
- package/dist/TFCtest/lastFile.txt +1 -0
- package/dist/allocation.js +2 -0
- package/dist/allocation.js.map +1 -1
- package/dist/balancer.js +8 -6
- package/dist/balancer.js.map +1 -1
- package/dist/bot.js +41 -16
- package/dist/bot.js.map +1 -1
- package/dist/gemini.js +72 -36
- package/dist/gemini.js.map +1 -1
- package/dist/ginit.js +41 -3
- package/dist/ginit.js.map +1 -1
- package/dist/init.js +37 -0
- package/dist/init.js.map +1 -1
- package/dist/krak2gem.js +7 -2
- package/dist/krak2gem.js.map +1 -1
- package/dist/manager.js +4 -3
- package/dist/manager.js.map +1 -1
- package/dist/reports.js +42 -32
- package/dist/reports.js.map +1 -1
- package/dist/safestore.js +127 -34
- package/dist/safestore.js.map +1 -1
- package/dist/savings.js.map +1 -1
- package/dist/test/kraken.test.js +2 -1
- package/dist/test/kraken.test.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/web.js +4 -4
- package/dist/web.js.map +1 -1
- package/gemini.ts +405 -0
- package/ginit.ts +45 -3
- package/init.ts +42 -0
- package/krak2gem.ts +7 -3
- package/manager.ts +5 -4
- package/new-contents.txt +130 -0
- package/old-contents.txt +129 -0
- package/package.json +3 -1
- package/reports.ts +41 -32
- package/safestore.ts +138 -36
- package/savings.ts +38 -13
- package/static/client.js +3 -1
- package/test/gem.test.js +28 -7
- package/test/kraken.test.ts +2 -1
- package/web.ts +5 -5
- package/gemini.js +0 -291
- package/savings.d.ts +0 -30
- package/test/mock-example.test.ts +0 -54
package/README.md
CHANGED
|
@@ -1,63 +1,63 @@
|
|
|
1
|
-
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
|
2
|
-
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
|
1
|
+
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
|
2
|
+
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
|
3
3
|
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
|
|
4
|
-
|
|
5
|
-
- [Release Notes for version 1.4](#release-notes-for-version-14)
|
|
6
|
-
- [kraken-grid BETA](#kraken-grid-beta)
|
|
7
|
-
- [Upgrading](#upgrading)
|
|
8
|
-
- [Installation](#installation)
|
|
9
|
-
- [Usage](#usage)
|
|
10
|
-
- [How the author (Dave) does it for himself and others:](#how-the-author-dave-does-it-for-himself-and-others)
|
|
11
|
-
- [Discussion of the `adjust` command.](#discussion-of-the-adjust-command)
|
|
12
|
-
- [Web UI](#web-ui)
|
|
13
|
-
- [Orders table](#orders-table)
|
|
14
|
-
- [Allocation table](#allocation-table)
|
|
15
|
-
- [Assets table](#assets-table)
|
|
16
|
-
- [Pie Charts](#pie-charts)
|
|
17
|
-
- [Changing your password](#changing-your-password)
|
|
18
|
-
- [Mistyped passwords](#mistyped-passwords)
|
|
19
|
-
- [Command Line Interface](#command-line-interface)
|
|
20
|
-
- [Trading](#trading)
|
|
21
|
-
- [addlev](#addlev)
|
|
22
|
-
- [delev](#delev)
|
|
23
|
-
- [buy](#buy)
|
|
24
|
-
- [sell](#sell)
|
|
25
|
-
- [kill](#kill)
|
|
26
|
-
- [limits](#limits)
|
|
27
|
-
- [less](#less)
|
|
28
|
-
- [more](#more)
|
|
29
|
-
- [Information Gathering](#information-gathering)
|
|
30
|
-
- [assets](#assets)
|
|
31
|
-
- [capGains](#capgains)
|
|
32
|
-
- [list [Search]](#list-search)
|
|
33
|
-
- [margin](#margin)
|
|
34
|
-
- [report](#report)
|
|
35
|
-
- [show](#show)
|
|
36
|
-
- [verbose](#verbose)
|
|
37
|
-
- [web](#web)
|
|
38
|
-
- [Bot Management](#bot-management)
|
|
39
|
-
- [adjust](#adjust)
|
|
40
|
-
- [allocate](#allocate)
|
|
41
|
-
- [allocation](#allocation)
|
|
42
|
-
- [asset](#asset)
|
|
43
|
-
- [auto](#auto)
|
|
44
|
-
- [manual](#manual)
|
|
45
|
-
- [balance](#balance)
|
|
46
|
-
- [notest](#notest)
|
|
47
|
-
- [quit](#quit)
|
|
48
|
-
- [risky](#risky)
|
|
49
|
-
- [refnum](#refnum)
|
|
50
|
-
- [reset](#reset)
|
|
51
|
-
- [safe](#safe)
|
|
52
|
-
- [set](#set)
|
|
53
|
-
- [Experimental features (Not Recommended and not well tested)](#experimental-features-not-recommended-and-not-well-tested)
|
|
54
|
-
- [ws - EXPERIMENTAL](#ws---experimental)
|
|
55
|
-
- [Internals](#internals)
|
|
56
|
-
- [Userref](#userref)
|
|
57
|
-
- [Partial Execution](#partial-execution)
|
|
58
|
-
- [HELP!](#help)
|
|
59
|
-
|
|
60
|
-
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
|
4
|
+
|
|
5
|
+
- [Release Notes for version 1.4](#release-notes-for-version-14)
|
|
6
|
+
- [kraken-grid BETA](#kraken-grid-beta)
|
|
7
|
+
- [Upgrading](#upgrading)
|
|
8
|
+
- [Installation](#installation)
|
|
9
|
+
- [Usage](#usage)
|
|
10
|
+
- [How the author (Dave) does it for himself and others:](#how-the-author-dave-does-it-for-himself-and-others)
|
|
11
|
+
- [Discussion of the `adjust` command.](#discussion-of-the-adjust-command)
|
|
12
|
+
- [Web UI](#web-ui)
|
|
13
|
+
- [Orders table](#orders-table)
|
|
14
|
+
- [Allocation table](#allocation-table)
|
|
15
|
+
- [Assets table](#assets-table)
|
|
16
|
+
- [Pie Charts](#pie-charts)
|
|
17
|
+
- [Changing your password](#changing-your-password)
|
|
18
|
+
- [Mistyped passwords](#mistyped-passwords)
|
|
19
|
+
- [Command Line Interface](#command-line-interface)
|
|
20
|
+
- [Trading](#trading)
|
|
21
|
+
- [addlev](#addlev)
|
|
22
|
+
- [delev](#delev)
|
|
23
|
+
- [buy](#buy)
|
|
24
|
+
- [sell](#sell)
|
|
25
|
+
- [kill](#kill)
|
|
26
|
+
- [limits](#limits)
|
|
27
|
+
- [less](#less)
|
|
28
|
+
- [more](#more)
|
|
29
|
+
- [Information Gathering](#information-gathering)
|
|
30
|
+
- [assets](#assets)
|
|
31
|
+
- [capGains](#capgains)
|
|
32
|
+
- [list [Search]](#list-search)
|
|
33
|
+
- [margin](#margin)
|
|
34
|
+
- [report](#report)
|
|
35
|
+
- [show](#show)
|
|
36
|
+
- [verbose](#verbose)
|
|
37
|
+
- [web](#web)
|
|
38
|
+
- [Bot Management](#bot-management)
|
|
39
|
+
- [adjust](#adjust)
|
|
40
|
+
- [allocate](#allocate)
|
|
41
|
+
- [allocation](#allocation)
|
|
42
|
+
- [asset](#asset)
|
|
43
|
+
- [auto](#auto)
|
|
44
|
+
- [manual](#manual)
|
|
45
|
+
- [balance](#balance)
|
|
46
|
+
- [notest](#notest)
|
|
47
|
+
- [quit](#quit)
|
|
48
|
+
- [risky](#risky)
|
|
49
|
+
- [refnum](#refnum)
|
|
50
|
+
- [reset](#reset)
|
|
51
|
+
- [safe](#safe)
|
|
52
|
+
- [set](#set)
|
|
53
|
+
- [Experimental features (Not Recommended and not well tested)](#experimental-features-not-recommended-and-not-well-tested)
|
|
54
|
+
- [ws - EXPERIMENTAL](#ws---experimental)
|
|
55
|
+
- [Internals](#internals)
|
|
56
|
+
- [Userref](#userref)
|
|
57
|
+
- [Partial Execution](#partial-execution)
|
|
58
|
+
- [HELP!](#help)
|
|
59
|
+
|
|
60
|
+
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
|
61
61
|
|
|
62
62
|
# Release Notes for version 1.4
|
|
63
63
|
This project has been converted to Typescript. There are also a few changes on the way to supporting the Gemini Exchange (using gemini-grid instead of kraken-grid). If you use both, lucky you! Kraken asked me to close my account after I got arrested for trading Bitcoin. See https://litmocracy.blogspot.com/2024/06/daves-narrative.html, the beginning of a book about it for more information. I have not tested using both Gemini and Kraken with the same instance. If you want to help, consider [writing some unit tests](https://github.com/dscotese/kraken-grid/issues)!
|
|
@@ -72,13 +72,18 @@ This version stores your API key and secret using your password. This informati
|
|
|
72
72
|
|
|
73
73
|
## Installation
|
|
74
74
|
1. Get your API key and secret from Kraken. Otherwise, you will have to go through this process again if you want to run kraken on a machine that doesn't have these keys yet, or if you forget your password.
|
|
75
|
-
- 1.1
|
|
76
|
-
- 1.2
|
|
77
|
-
- 1.3 Click "API"
|
|
78
|
-
- 1.4
|
|
79
|
-
- 1.5 We recommend that you give your key a better description.
|
|
80
|
-
- 1.6 Check the "Query Funds" box under "Funds" and all the boxes under "Orders & Trades"
|
|
81
|
-
|
|
75
|
+
- 1.1 Sign in to your Kraken account and click on the profile icon in the upper right corner.
|
|
76
|
+
- 1.2 Select "Settings" from the dropdown menu.
|
|
77
|
+
- 1.3 Click the "API" tab.
|
|
78
|
+
- 1.4 Click "Create API key".
|
|
79
|
+
- 1.5 We recommend that you give your key a better description (this is now called "Key Description").
|
|
80
|
+
- 1.6 Check the "Query Funds" box under "Funds Permissions" and all the boxes under "Orders & Trades Permissions":
|
|
81
|
+
- Query Open Orders & Trades
|
|
82
|
+
- Query Closed Orders & Trades
|
|
83
|
+
- Modify Orders
|
|
84
|
+
- Cancel/Close Orders
|
|
85
|
+
- 1.7 Click "Generate key".
|
|
86
|
+
- 1.8 IMPORTANT: Copy and save both the API Key and Private Key immediately in a secure location (like a password manager). The Private Key will not be shown again after you leave this page
|
|
82
87
|
2. Install [NodeJS](https://nodejs.org/)
|
|
83
88
|
3. Run `npm -g install kraken-grid` from a command line ("Command Prompt", "Terminal Window", or "Shell").
|
|
84
89
|
|
|
@@ -323,3 +328,4 @@ Because grid orders have conditional closes (at a price I'll call C, for close,
|
|
|
323
328
|
This code is messy. It works for me and I didn't want to keep waiting until I cleaned it up to publish it. One of the major motivations I have for publishing it is that as more people use a strategy like "grid trader" to balance their savings, the prices of the cryptos with which they do it will become more stable.
|
|
324
329
|
|
|
325
330
|
All calls to @nothingisdead's [Kraken-API](https://github.com/nothingisdead/npm-kraken-api) (which I have copied and renamed to kraka-djs to add CancelAll) are made through a function I called `kapi` so that any other exchange could be used by updating that funtion to translate Kraken's APIs to those of other exchanges.
|
|
331
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
TFCtest/2026-02-20T13-12-20.json
|
package/allocation.ts
CHANGED
|
@@ -481,6 +481,10 @@ export const AllocCon = async (
|
|
|
481
481
|
let str = `\nticker\ttarget\t(adjusted)\t(Range)\t(apct,ppct)\t${compare
|
|
482
482
|
? `${compare.name}\tdiff\t`
|
|
483
483
|
: '\t\t'}Total: ${total}`;
|
|
484
|
+
|
|
485
|
+
// Remove any degenerate asset entries:
|
|
486
|
+
assets = assets.filter(x =>
|
|
487
|
+
(typeof x.ticker == "string" && x.ticker.length > 0));
|
|
484
488
|
|
|
485
489
|
await Promise.all(assets.map(async (a) => {
|
|
486
490
|
await get(a.ticker); // Forces an update
|
package/balancer.ts
CHANGED
|
@@ -98,14 +98,15 @@ const Balancer = (config: BalancerConfig): BalancerInstance => {
|
|
|
98
98
|
// processes the open orders.
|
|
99
99
|
// -------------------------------------------------------
|
|
100
100
|
// We are replacing the grid for p.pair, so let's cancel
|
|
101
|
-
// all its orders.
|
|
102
|
-
|
|
103
|
-
.
|
|
104
|
-
|
|
101
|
+
// all its orders if there are any.
|
|
102
|
+
if(bot.portfolio.O) {
|
|
103
|
+
const toCancel = bot.portfolio.O.filter(o => [p.pair, po.altname].includes(o[1].descr.pair))
|
|
104
|
+
.map(ae => ae[0]);
|
|
105
|
+
console.log(`${bot.FLAGS.safe ? 'NOT ' : ''}Cancelling`, toCancel);
|
|
105
106
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
107
|
+
if (!bot.FLAGS.safe && toCancel)
|
|
108
|
+
await bot.kill(toCancel);
|
|
109
|
+
}
|
|
109
110
|
const Ordered = await bot.order(p.type, p.pair, p.price, p.amt,
|
|
110
111
|
bot.getLev(bot.portfolio, p.type, p.price, p.amt, po.base, false),
|
|
111
112
|
0, p.type === 'buy' ? sP : bP); // uref, close
|
package/bot.ts
CHANGED
|
@@ -314,7 +314,8 @@ export default function Bot(config: any): BotInstance {
|
|
|
314
314
|
portfolio.limits = p.limits ? p.limits : [0,-1];
|
|
315
315
|
portfolio.lastUpdate = p.lastUpdate ? p.lastUpdate : null;
|
|
316
316
|
portfolio.Allocation = await AllocCon(config,
|
|
317
|
-
p.Alloc ? p.Alloc.assets
|
|
317
|
+
p.Alloc ? p.Alloc.assets.filter(x =>
|
|
318
|
+
(typeof x.ticker == "string" && x.ticker.length>0)) : undefined);
|
|
318
319
|
Reports = ReportCon(config.bot);
|
|
319
320
|
config.report = Reports;
|
|
320
321
|
}
|
|
@@ -450,7 +451,7 @@ export default function Bot(config: any): BotInstance {
|
|
|
450
451
|
if(gPrices.length === 0) { // When we have no grid prices, collect orders.
|
|
451
452
|
console.log("Reading grid from 20 closed orders...");
|
|
452
453
|
const closed = await moreOrders(20);
|
|
453
|
-
const closedIDs = closed?.keysFwd()
|
|
454
|
+
const closedIDs = closed?.keysFwd?.() ?? [];
|
|
454
455
|
if(closed && closedIDs.length > 0) {
|
|
455
456
|
let counter = closedIDs.length-1;
|
|
456
457
|
lCOts = closed?.orders[closedIDs[counter]].closetm || 0;
|
|
@@ -463,7 +464,7 @@ export default function Bot(config: any): BotInstance {
|
|
|
463
464
|
const cd = new Date(oo.closetm * 1000);
|
|
464
465
|
let gp:GridPoint | undefined = gPrices.find((x:any) => x.userref===ur); // If we already saw this grid point.
|
|
465
466
|
if( counter < 5 ) {
|
|
466
|
-
console.log(o,ur,op,od.type,od.close,`${cd.getFullYear()}/${1+cd.getMonth()
|
|
467
|
+
console.log(o,ur,op,od.type,oo.vol_exec,od.close,`${cd.getFullYear()}/${1+cd.getMonth()
|
|
467
468
|
}/${cd.getDate()}`,cd.getHours(),cd.getMinutes(),cd.getSeconds());
|
|
468
469
|
}
|
|
469
470
|
counter -= 1;
|
|
@@ -647,7 +648,7 @@ export default function Bot(config: any): BotInstance {
|
|
|
647
648
|
// Reference Number.
|
|
648
649
|
async function kill(o,oa:KOrder[]=[]):Promise<APIResponse> {
|
|
649
650
|
let killed;
|
|
650
|
-
if(o === 0) {
|
|
651
|
+
if(o === 0 || /^0$/.test(o)) {
|
|
651
652
|
const killAll = prompt("Cancel ALL orders? [y/N]");
|
|
652
653
|
if(/^y/i.test(killAll)) {
|
|
653
654
|
killed = await kapi('CancelAll');
|
|
@@ -837,8 +838,15 @@ console.log("[p,np,dp,t,hp,lp,b,ma,f,tot1,ov,a,a2,t2,t2s]:",
|
|
|
837
838
|
if(!c.hasClose) { // If any doesn't have a close, combine them and add one.
|
|
838
839
|
console.log(421,Object.values(c.ids));
|
|
839
840
|
const cleared = await kill(c.ids.length>1?c.ids:c.ids[0], portfolio.O);
|
|
840
|
-
if( cleared
|
|
841
|
+
if( cleared?.result?.descr === 'Ignored' || cleared?.result?.count === 0 )
|
|
841
842
|
throw new Error('No such order(s).');
|
|
843
|
+
if( cleared.result.pending ) {
|
|
844
|
+
// Use QueryOrders to wait until they are gone.
|
|
845
|
+
await sleep(1000);
|
|
846
|
+
let qoRes = await kapi(['QueryOrders',c.ids.join(',')]);
|
|
847
|
+
if( qoRes.result.status != 'canceled' )
|
|
848
|
+
throw new Error('Cancellation took too long.');
|
|
849
|
+
}
|
|
842
850
|
await order(c.type,sym,price, toDec(c.total,4),
|
|
843
851
|
c.lev,c.userref,c.open);
|
|
844
852
|
if(FLAGS.verbose) console.log(425,
|
|
@@ -850,7 +858,7 @@ console.log("[p,np,dp,t,hp,lp,b,ma,f,tot1,ov,a,a2,t2,t2s]:",
|
|
|
850
858
|
const traded = c.type==='buy' ? 'sold' : 'bought';
|
|
851
859
|
gp[traded]+=c.total;
|
|
852
860
|
}
|
|
853
|
-
// Do we need to extend the grid?
|
|
861
|
+
// Do we need to [extend] the grid?
|
|
854
862
|
// If we don't have a buy and a sell, then yes.
|
|
855
863
|
// --------------------------------------------
|
|
856
864
|
bs = bSidesP.find(b => b.pair===c.sym); // Was sym+'USD' but #USD Refactor
|
|
@@ -873,6 +881,22 @@ console.log("[p,np,dp,t,hp,lp,b,ma,f,tot1,ov,a,a2,t2,t2s]:",
|
|
|
873
881
|
let gpsell = Number(gp.sell);
|
|
874
882
|
let gpbuy = Number(gp.buy);
|
|
875
883
|
sp = Math.round(10**decimals*gpsell*gpsell/gpbuy)/10**decimals;
|
|
884
|
+
// eslint-disable-next-line no-await-in-loop
|
|
885
|
+
let newVol = -1 * await howMuch(sym, sp);
|
|
886
|
+
if(newVol < 0) {
|
|
887
|
+
// If vol is < 0, use a higher price instead of:
|
|
888
|
+
/* throw new Error(`At ${sp}, you'd have to 'sell' ${
|
|
889
|
+
newVol}, which means we're way out of balance.`);
|
|
890
|
+
return;
|
|
891
|
+
*/
|
|
892
|
+
sp = Math.round(10**decimals*gpsell**3/gpbuy**2)/10**decimals;
|
|
893
|
+
// eslint-disable-next-line no-await-in-loop
|
|
894
|
+
newVol = -1 * await howMuch(sym, sp);
|
|
895
|
+
if(newVol < 0) {
|
|
896
|
+
throw new Error(`Even at ${sp}, you'd have to 'sell' ${
|
|
897
|
+
newVol}, which means we're way out of balance.`);
|
|
898
|
+
}
|
|
899
|
+
}
|
|
876
900
|
// eslint-disable-next-line no-param-reassign
|
|
877
901
|
c.userref = makeUserRef('sell', c.sym, sp);
|
|
878
902
|
// We may already have this grid price but the order
|
|
@@ -890,13 +914,6 @@ console.log("[p,np,dp,t,hp,lp,b,ma,f,tot1,ov,a,a2,t2,t2s]:",
|
|
|
890
914
|
} to close at ${gp.sell}`);
|
|
891
915
|
}
|
|
892
916
|
// eslint-disable-next-line no-await-in-loop
|
|
893
|
-
const newVol = -1 * await howMuch(sym, sp);
|
|
894
|
-
if(newVol < 0) {
|
|
895
|
-
console.log("At",sp,"you'd have to 'sell'",
|
|
896
|
-
`${newVol}, which means we're way out of balance.`);
|
|
897
|
-
return;
|
|
898
|
-
}
|
|
899
|
-
// eslint-disable-next-line no-await-in-loop
|
|
900
917
|
await order('sell',c.sym,sp,newVol,
|
|
901
918
|
getLev(portfolio,'sell',sp,newVol,c.sym,false),c.userref,
|
|
902
919
|
gpsell);
|
|
@@ -907,7 +924,7 @@ console.log("[p,np,dp,t,hp,lp,b,ma,f,tot1,ov,a,a2,t2,t2s]:",
|
|
|
907
924
|
gp = gp as GridPoint;
|
|
908
925
|
let gpsell = Number(gp.sell);
|
|
909
926
|
let gpbuy = Number(gp.buy);
|
|
910
|
-
bp = Math.round(decimals*gpbuy*gpbuy/gpsell)/decimals;
|
|
927
|
+
bp = Math.round(10**decimals*gpbuy*gpbuy/gpsell)/10**decimals;
|
|
911
928
|
// eslint-disable-next-line no-param-reassign
|
|
912
929
|
c.userref = makeUserRef('buy', c.sym, bp);
|
|
913
930
|
// We may already have this grid price but the order
|
|
@@ -926,11 +943,20 @@ console.log("[p,np,dp,t,hp,lp,b,ma,f,tot1,ov,a,a2,t2,t2s]:",
|
|
|
926
943
|
if(ngp.buy === ngp.sell) throw new Error("Bad Grid Point");
|
|
927
944
|
}
|
|
928
945
|
// eslint-disable-next-line no-await-in-loop
|
|
929
|
-
|
|
946
|
+
let newVol = await howMuch(sym, bp);
|
|
930
947
|
if(newVol < 0) {
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
948
|
+
// If vol is < 0, use a higher price instead of:
|
|
949
|
+
/* throw new Error(`At ${bp}, you'd have to 'buy' ${
|
|
950
|
+
newVol}, which means we're way out of balance.`);
|
|
951
|
+
return;
|
|
952
|
+
*/
|
|
953
|
+
bp = Math.round(10**decimals*gpbuy**3/gpsell**2)/10**decimals;
|
|
954
|
+
// eslint-disable-next-line no-await-in-loop
|
|
955
|
+
newVol = await howMuch(sym, bp);
|
|
956
|
+
if(newVol < 0) {
|
|
957
|
+
throw new Error(`Even at ${bp}, you'd have to 'buy' ${
|
|
958
|
+
newVol}, which means we're way out of balance.`);
|
|
959
|
+
}
|
|
934
960
|
}
|
|
935
961
|
// eslint-disable-next-line no-await-in-loop
|
|
936
962
|
await order('buy',c.sym,bp,newVol,
|