Giter VIP home page Giter VIP logo

coinbase-pro-trading-toolkit's Introduction

Coinbase Pro Trading toolkit

CircleCI

npm

Note: The gdax-trading-toolkit package is deprecated and might have to be removed from NPM. Please migrate to the coinbase-pro-trading-toolkit package to ensure future compatibility.

Provide all the tools traders need, both professional and hobbyist alike, to create automated trading bots on the Coinbase Pro and supported digital asset exchanges. Note: Node 7.6 or above is required.

Recommended:

  • Node 9.4 or above
  • Typescript 2.7

Install

yarn add coinbase-pro-trading-toolkit

Test

Run the included test suite with the command

yarn test

Run

The src/samples folder contains many working demo scripts showcasing different aspects of the toolkit, while the tutorials folder contains running demo programs to accompany the CBPTT documentation.

Documentation

The CBPTT documentation contains blogs, reference material and step-by-step tutorials

Disclaimer

This software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and non-infringement. In no event shall the authors, copyright holders, or Coinbase Inc. be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the software.

coinbase-pro-trading-toolkit's People

Contributors

abe238 avatar akahan avatar ameobea avatar amerzel avatar atomantic avatar balupton avatar blair avatar cjs77 avatar discosultan avatar ericcrosson avatar fb55 avatar jbaczuk avatar jcronq avatar jma353 avatar kahmienah avatar kostola avatar maxbeatty avatar mihar avatar mkondel avatar mmkal avatar nhippenmeyer avatar oatssss avatar pzagor2 avatar rmm5t avatar sds avatar udnisap avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

coinbase-pro-trading-toolkit's Issues

Running scripts from /tutorials

I just cloned the project and started playing with the examples from /tutorials folder.

The gtt_tutorials_feed.html suggest running them with ts-node src/tutorials/t001_feeds.ts ( wrong path, it should be without src/) the problem is that the GTT import from gdax-trading-toolkit is not available and you can't fix this with npm i gdax-trading-toolkit because you can't reference dependency of itself.

Would it make sense to have the import reference the files from build folder? import * as GTT from '../build/src/index';

If these tutorials are not meant to run from the root of the project, but more as a showcase if would be good to add a note to the docs.

Cancelled order not in my book

I want to execute some code after a trade is completed/fully filled so I have the following event listener in place:

trader.on('Trader.trade-finalized', (msg: TradeFinalizedMessage) => {
    logger.log('info', 'Order complete', JSON.stringify(msg));
});

Now I'm getting the following message instead: 2017-10-28T21:07:28.294Z - warn: Trader: Cancelled order not in my book...

Why is this happening and how to fix it?

bittrex-feed subscribe()

should be asynchronous, and return a Promise instead of boolean, because the two
this.client.call()s in the function are asynchronous, and a successful subscription is dependent on their results

Consider a `SettledOrder` type

We should consider adding SettledOrder as a distinct type to LiveOrder

This would add fields that are not typically known for 'live' orders, such as settled time and fees charged.

The price semantics are also potentially different (e.g. settled market orders are often matched against multiple resting orders and so only have an average price)

bittrex feed negotiate unknown

Looks like maybe the signalr client is totally not working for the bittrex feed?

Error Message:  Negotiate Unknown
Exception:  undefined
Error Data:  503

is the error message I get, and

➜  my-gdax-tt git:(bittrex) ✗ grep -inIEr --color=ALWAYS "Negotiate Unknown" .
./node_modules/signalr-client/signalR.js:110:                    onError('Negotiate Unknown', undefined, res.statusCode);

Git Error [Failed to execute] for node-rate-limiter (exit code 128)

Git returns the following error:

Failed to execute "git ls-remote –tags –heads git://github.com/jhurliman/node-rate-limiter.git"

One way of solving this is running:
git config url."https://".insteadOf git://

And the second was to change the url in the package.json and yarn.lock from 'git://' to 'https://'

This error is received when running npm install or yarn add on an Windows PC

Removing crypto package

Does gdax-tt have a dependency on v0.0.3 of the crypto package? Since it's deprecated it would be cleaner to remove it.

Is there a way to get my current holding positions?

This is definitely a question rather than issue, not sure where is the best place to ask.

What is the best way to find out my current positions, like cash, BTC, ETH etc. As I am making trades, when trade get partially filled or cancelled, I'd like to get a subscription of my latest holding positions.

Graceful shutdown of WebSocket feed

Version: 0.1.19

Currently calling feed.disconnect() mostly works, except it leaves the connectionChecker interval alive. This causes the node process to hang indefinitely when trying to shutdown the feed.

This looks like the place where we need to clearInterval().

Somewhere in the disconnect() / close() path I think just needs a:

clearInterval(this.connectionChecker);

I added this in my own code for now and it does indeed let it gracefully exit.

Bad Request

so I am getting the bellow message but only when my bot is trading massive amounts IDT it is exceeding the 10 request per second. How do I get a better idea of what the error message for? I have also added the code that I use bellow any help would be awesome.

Error: A GDAX API request failed. Bad Request.

        -------Order-------
        type:order
        Time:null
        ProductId:LTC-USD
        OrderType:limit
        Side:buy
        Size:1
        Price:60.14
gdaxAPI.placeOrder(order).then((result: LiveOrder) => {
            Message.log(`Order to ${side} ${amount} 'LTC-USD' for${price}. Result: ${result.status} 
            
            -------Order-------
            type:${order.type}
            Time:${order.time}
            ProductId:${order.productId}
            OrderType:${order.orderType}
            Side:${order.side}
            Size:${order.size}
            Price:${order.price}
            
            `);

        }).catch(
            function (message:any) {
            Message.sendMessage(`${message}.
            
            -------Order-------
            type:${order.type}
            Time:${order.time}
            ProductId:${order.productId}
            OrderType:${order.orderType}
            Side:${order.side}
            Size:${order.size}
            Price:${order.price}
            `);
            Message.log(order);

SyntaxError: Unexpected token {

Hello,
After installing via npm I get the following error.

~$ ./node_modules/.bin/gdaxConsole --product BTC-USD -t
/home/NAME/node_modules/gdax-trading-toolkit/build/src/consoles/gdaxConsole.js:96
let { type, amount, cur, coinbase_id } = program.transfer.split(',');
^

SyntaxError: Unexpected token {
at exports.runInThisContext (vm.js:53:16)
at Module._compile (module.js:374:25)
at Object.Module._extensions..js (module.js:417:10)
at Module.load (module.js:344:32)
at Function.Module._load (module.js:301:12)
at Function.Module.runMain (module.js:442:10)
at startup (node.js:136:18)
at node.js:966:3

Unable to place orders in GDAX with the sample

Unable to place orders based on the sample t005_alertTrader.ts

/***************************************************************************************************************************
 * @license                                                                                                                *
 * Copyright 2017 Coinbase, Inc.                                                                                           *
 *                                                                                                                         *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance          *
 * with the License. You may obtain a copy of the License at                                                               *
 *                                                                                                                         *
 * http://www.apache.org/licenses/LICENSE-2.0                                                                              *
 *                                                                                                                         *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on     *
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the                      *
 * License for the specific language governing permissions and limitations under the License.                              *
 ***************************************************************************************************************************/

import * as GTT from "gdax-trading-toolkit";
import { Big } from "gdax-trading-toolkit/build/src/lib/types";
import { GDAX_WS_FEED, GDAXFeed, GDAXFeedConfig } from "gdax-trading-toolkit/build/src/exchanges";
import { GDAX_API_URL } from "gdax-trading-toolkit/build/src/exchanges/gdax/GDAXExchangeAPI";
import { PlaceOrderMessage, TickerMessage } from "gdax-trading-toolkit/build/src/core";
import { LiveOrder } from "gdax-trading-toolkit/build/src/lib";

const logger = GTT.utils.ConsoleLoggerFactory();
const product = 'ETH-USD';
/**
 * Remember to set GDAX_KEY, GDAX_SECRET and GDAX_PASSPHRASE envars to allow trading
 */




const gdaxAPI = GTT.Factories.GDAX.DefaultAPI(logger);
const [base, quote] = product.split('-');
const spread = Big('0.05');

GTT.Factories.GDAX.getSubscribedFeeds(options, [product]).then((feed: GDAXFeed) => {
    GTT.Core.createTickerTrigger(feed, product)
        .setAction((ticker: TickerMessage) => {
            const currentPrice = ticker.price;
            GTT.Core.createPriceTrigger(feed, product, currentPrice.minus(spread))
                .setAction((event: TickerMessage) => {
                    console.log('Price Trigger', `${base} price has fallen and is now ${event.price} ${quote} on ${product} on GDAX`);
                    submitTrade('buy', '0.005');
                });
        });
});

function submitTrade(side: string, amount: string) {
    const order: PlaceOrderMessage = {
        type: 'order',
        time: null,
        productId: product,
        orderType: 'limit',
        side: side,
        size: amount
    };
    console.log('Order executed', `Order to ${order.side} 0.1 ${base} placed.`);
    console.log(order);
    
    gdaxAPI.placeOrder(order).then((result: LiveOrder) => {
        
        console.log('Order executed', `Order to ${order.side} 0.1 ${base} placed. Result: ${result.status}`);
    });
}

This is the error I am getting on the place order.

2017-11-24T20:32:26.533Z - error: The websocket feed to wss://ws-feed.gdax.com (authenticated) has reported an error. If necessary, we will reconnect.

{
  "type": "ticker",
  "sequence": 1538048915,
  "product_id": "ETH-USD",
  "price": "462.76000000",
  "open_24h": "417.52000000",
  "volume_24h": "316236.70621607",
  "low_24h": "462.76000000",
  "high_24h": "469.50000000",
  "volume_30d": "4030617.08136485",
  "best_bid": "462.75",
  "best_ask": "462.76",
  "side": "buy",
  "time": "2017-11-24T20:30:52.968000Z",
  "trade_id": 16874695,
  "last_size": "0.00032317"
}

How do I debug the error? Thanks

Sequence number initialization from snapshot

I'm running code from the samples and it constantly reconnects because it's receiving LiveOrderbook.skippedMessage here.

I'm not using any authentication. When I add a log statement here I can see that the snapshot message contains a sequence of 1.

Here is some sample output:

2017-09-29T00:47:16.409Z - info: Creating new Websocket connection to wss://ws-feed.gdax.com
2017-09-29T00:47:16.427Z - debug: Reconnecting to wss://ws-feed.gdax.com  in 0 seconds...
2017-09-29T00:47:16.427Z - debug: Closing existing socket prior to reconnecting to wss://ws-feed.gdax.com
2017-09-29T00:47:16.672Z - debug: Connection to wss://ws-feed.gdax.com  has been established.
2017-09-29T00:47:16.672Z - debug: Sending {"type":"subscribe","product_ids":["BTC-USD"],"channels":["level2","matches","ticker","user","heartbeat"]} message to WS server
2017-09-29T00:47:17.159Z - info: Snapshot received by LiveOrderbook Demo
2017-09-29T00:47:17.160Z - info: Dropped a message. Expected 2 but received 4118596218.
SKIPPED MESSAGE { expected_sequence: 2, sequence: 4118596218 }
Reconnecting to feed
2017-09-29T00:47:17.162Z - debug: Reconnecting to wss://ws-feed.gdax.com  in 0 seconds...
2017-09-29T00:47:17.162Z - debug: Closing existing socket prior to reconnecting to wss://ws-feed.gdax.com
2017-09-29T00:47:17.163Z - debug: GDAX Feed subscriptions confirmed type=subscriptions, channels=[name=level2, product_ids=[BTC-USD], name=matches, product_ids=[BTC-USD], name=ticker, product_ids=[BTC-USD], name=user, product_ids=[BTC-USD], name=heartbeat, product_ids=[BTC-USD]]
2017-09-29T00:47:17.400Z - debug: Connection to wss://ws-feed.gdax.com  has been established.
2017-09-29T00:47:17.401Z - debug: Resubscribing to BTC-USD...
2017-09-29T00:47:17.401Z - debug: Sending {"type":"subscribe","product_ids":["BTC-USD"],"channels":["level2","matches","ticker","user","heartbeat"]} message to WS server
2017-09-29T00:47:17.401Z - debug: Sending {"type":"subscribe","product_ids":["BTC-USD"],"channels":["level2","matches","ticker","user","heartbeat"]} message to WS server
2017-09-29T00:47:17.402Z - debug: Reconnection to BTC-USD successful
2017-09-29T00:47:17.854Z - info: Snapshot received by LiveOrderbook Demo
2017-09-29T00:47:17.854Z - info: Dropped a message. Expected 12 but received 4118596218.
SKIPPED MESSAGE { expected_sequence: 12, sequence: 4118596218 }
Reconnecting to feed
2017-09-29T00:47:17.855Z - debug: Reconnecting to wss://ws-feed.gdax.com  in 0 seconds...
2017-09-29T00:47:17.855Z - debug: Closing existing socket prior to reconnecting to wss://ws-feed.gdax.com
2017-09-29T00:47:17.855Z - debug: GDAX Feed subscriptions confirmed type=subscriptions, channels=[name=level2, product_ids=[BTC-USD], name=matches, product_ids=[BTC-USD], name=ticker, product_ids=[BTC-USD], name=user, product_ids=[BTC-USD], name=heartbeat, product_ids=[BTC-USD]]
2017-09-29T00:47:18.154Z - info: Snapshot received by LiveOrderbook Demo
2017-09-29T00:47:18.154Z - info: Dropped a message. Expected 12 but received 4118596218.
SKIPPED MESSAGE { expected_sequence: 12, sequence: 4118596218 }
Reconnecting to feed
2017-09-29T00:47:18.154Z - debug: Reconnecting to wss://ws-feed.gdax.com  in 0 seconds...
2017-09-29T00:47:18.154Z - debug: Closing existing socket prior to reconnecting to wss://ws-feed.gdax.com
2017-09-29T00:47:18.155Z - debug: GDAX Feed subscriptions confirmed type=subscriptions, channels=[name=level2, product_ids=[BTC-USD], name=matches, product_ids=[BTC-USD], name=ticker, product_ids=[BTC-USD], name=user, product_ids=[BTC-USD], name=heartbeat, product_ids=[BTC-USD]]
2017-09-29T00:47:18.358Z - debug: Connection to wss://ws-feed.gdax.com  has been established.
2017-09-29T00:47:18.358Z - debug: Resubscribing to BTC-USD...
2017-09-29T00:47:18.358Z - debug: Sending {"type":"subscribe","product_ids":["BTC-USD"],"channels":["level2","matches","ticker","user","heartbeat"]} message to WS server
2017-09-29T00:47:18.359Z - debug: Sending {"type":"subscribe","product_ids":["BTC-USD"],"channels":["level2","matches","ticker","user","heartbeat"]} message to WS server
2017-09-29T00:47:18.359Z - debug: Reconnection to BTC-USD successful
2017-09-29T00:47:18.796Z - info: Snapshot received by LiveOrderbook Demo
2017-09-29T00:47:18.796Z - info: Dropped a message. Expected 24 but received 4118596218.
SKIPPED MESSAGE { expected_sequence: 24, sequence: 4118596218 }
Reconnecting to feed
2017-09-29T00:47:18.797Z - debug: Reconnecting to wss://ws-feed.gdax.com  in 0 seconds...
2017-09-29T00:47:18.797Z - debug: Closing existing socket prior to reconnecting to wss://ws-feed.gdax.com
2017-09-29T00:47:18.797Z - debug: GDAX Feed subscriptions confirmed type=subscriptions, channels=[name=level2, product_ids=[BTC-USD], name=matches, product_ids=[BTC-USD], name=ticker, product_ids=[BTC-USD], name=user, product_ids=[BTC-USD], name=heartbeat, product_ids=[BTC-USD]]
2017-09-29T00:47:19.048Z - info: Snapshot received by LiveOrderbook Demo
2017-09-29T00:47:19.049Z - info: Dropped a message. Expected 24 but received 4118596218.
SKIPPED MESSAGE { expected_sequence: 24, sequence: 4118596218 }
Reconnecting to feed
2017-09-29T00:47:19.049Z - debug: Reconnecting to wss://ws-feed.gdax.com  in 0 seconds...
2017-09-29T00:47:19.049Z - debug: Closing existing socket prior to reconnecting to wss://ws-feed.gdax.com
2017-09-29T00:47:19.049Z - debug: GDAX Feed subscriptions confirmed type=subscriptions, channels=[name=level2, product_ids=[BTC-USD], name=matches, product_ids=[BTC-USD], name=ticker, product_ids=[BTC-USD], name=user, product_ids=[BTC-USD], name=heartbeat, product_ids=[BTC-USD]]

Incorrect interpreter path in ./node_modules/.bin/gdaxConsole

Hi there,

This looks great!

I was going to test and see how it works but the first step failed:

$ ./node_modules/.bin/gdaxConsole --product BTC-USD -t
bash: ./node_modules/.bin/gdaxConsole: /bin/env: bad interpreter: No such file or directory

Changing the file to use /usr/bin/env instead of /bin/env fixed it. I noticed all the other files in that same folder are already using /usr/bin/env

Typescript errors on import

gdax-tt v0.1.16
node v8.3.0
typescript 2.5.3

Trying to follow along with the getting started guide. Trying to compile file with GTT import leads to following failure

import * as GTT from "gdax-trading-toolkit";
...
node_modules/gdax-trading-toolkit/build/src/core/HFTFilter.d.ts(22,22): error TS2415: Class 'HFTFilter' incorrectly extends base class 'Duplex'.
  Property '_write' is protected in type 'HFTFilter' but public in type 'Duplex'.
node_modules/gdax-trading-toolkit/build/src/core/LiveOrderbook.d.ts(39,22): error TS2415: Class 'LiveOrderbook' incorrectly extends base class 'Duplex'.
  Property '_write' is protected in type 'LiveOrderbook' but public in type 'Duplex'.
node_modules/gdax-trading-toolkit/build/src/core/MessageQueue.d.ts(67,22): error TS2415: Class 'MessageQueue' incorrectly extends base class 'Duplex'.
  Property '_write' is protected in type 'MessageQueue' but public in type 'Duplex'.
node_modules/gdax-trading-toolkit/build/src/core/RateLimiter.d.ts(21,22): error TS2415: Class 'RateLimiter' incorrectly extends base class 'Transform'.
  Property '_transform' is protected in type 'RateLimiter' but public in type 'Transform'.
node_modules/gdax-trading-toolkit/build/src/core/Trader.d.ts(46,22): error TS2415: Class 'Trader' incorrectly extends base class 'Writable'.
  Property '_write' is protected in type 'Trader' but public in type 'Writable'.
node_modules/gdax-trading-toolkit/build/src/exchanges/ExchangeFeed.d.ts(28,31): error TS2415: Class 'ExchangeFeed' incorrectly extends base class 'Readable'.
  Property '_read' is protected in type 'ExchangeFeed' but public in type 'Readable'.
node_modules/gdax-trading-toolkit/build/src/lib/StaticCommandSet.d.ts(20,22): error TS2415: Class 'StaticCommandSet' incorrectly extends base class 'Readable'.
  Property '_read' is protected in type 'StaticCommandSet' but public in type 'Readable'.
node_modules/gdax-trading-toolkit/build/src/utils/index.d.ts(3,29): error TS7016: Could not find a declaration file for module 'pushbullet'. '/app/node_modules/pushbullet/index.js' implicitly has an 'any' type.

Avoiding double execution of orders

Placing new orders is tricky because the same order could execute twice if a seemingly timed out order is retried. To solve this (at least on Poloniex, where it's a very real problem), a tiny placeholder order can be placed at a price that won't fill (so there's no risk if it's done twice) and then this placeholder order can be modified ("moveOrder") which is an idempotent operation.

Can't connect to feed with API key

I'm trying to run the last tutorial example for authenticating to the API but getting the follow errors when running:

``2017-09-15T04:28:12.084Z - debug: Sending {"type":"subscribe","product_ids":["ETH-USD"],"channels":["ticker","heartbeat"],"signature":"MYSIG","key":"MYKEY","timestamp":"thetimestamp","passphrase":"mypassphrase"} message to WS server
2017-09-15T04:28:12.086Z - debug: Reconnection to ETH-USD successful
2017-09-15T04:29:11.864Z - info: The websocket feed to wss://ws-feed.gdax.com (authenticated) has been closed by an external party. We will reconnect in 5 seconds code=1006, reason=
2017-09-15T04:29:11.864Z - debug: Reconnecting to wss://ws-feed.gdax.com (authenticated) in 5 seconds...

It just keeps looping doing this. I have triple checked that my key, secret, and passphrase are all set correctly. what's the deal? When I leave out my API creds, the example runs just fine.

Example script fails to connect

gdax-tt 0.1.16
node 8.3.0
typescript 2.5.3

Script pulled from example doc https://coinbase.github.io/gdax-tt/gtt_tutorials_feed.html#the-basics

import * as GTT from "gdax-trading-toolkit";
import { GDAXFeed } from "gdax-trading-toolkit/build/src/exchanges";
import { OrderbookMessage } from "gdax-trading-toolkit/build/src/core";

const logger = GTT.utils.ConsoleLoggerFactory();
const products: string[] = ["BTC-USD", "ETH-USD", "LTC-USD"];
const tallies: any = {};
products.forEach((product: string) => {
  tallies[product] = {};
});

let count = 0;

function printTallies() {}

GTT.Factories.GDAX
  .FeedFactory(logger, products)
  .then((feed: GDAXFeed) => {
    feed.on("data", (msg: OrderbookMessage) => {
      count++;
      if (!(msg as any).productId) {
        tallies.other += 1;
      } else {
        const tally = tallies[msg.productId];
        if (!tally[msg.type]) {
          tally[msg.type] = 0;
        }
        tally[msg.type] += 1;
      }
      if (count % 1000 === 0) {
        printTallies();
      }
    });
  })
  .catch((err: Error) => {
    logger.log("error", err.message);
    process.exit(1);
  });

Logs

2017-10-01T05:12:52.329Z - info: Creating new Websocket connection to wss://ws-feed.gdax.com 
2017-10-01T05:12:52.340Z - debug: Reconnecting to wss://ws-feed.gdax.com  in 0 seconds...
2017-10-01T05:12:52.340Z - debug: Closing existing socket prior to reconnecting to wss://ws-feed.gdax.com
2017-10-01T05:12:53.693Z - debug: Connection to wss://ws-feed.gdax.com  has been established.
2017-10-01T05:12:53.693Z - debug: Sending {"type":"subscribe","product_ids":["BTC-USD","ETH-USD","LTC-USD"],"channels":["level2","matches","ticker","user","heartbeat"]} message to WS server

/app/node_modules/gdax-trading-toolkit/node_modules/ws/lib/Sender.js:206
      bufferUtil.mask(data, mask, outputBuffer, dataOffset, dataLength);
                ^
TypeError: Cannot read property 'mask' of undefined
    at Sender.frameAndSend (/app/node_modules/gdax-trading-toolkit/node_modules/ws/lib/Sender.js:206:17)
    at /app/node_modules/gdax-trading-toolkit/node_modules/ws/lib/Sender.js:126:12
    at /app/node_modules/gdax-trading-toolkit/node_modules/ws/lib/PerMessageDeflate.js:313:5
    at afterWrite (_stream_writable.js:438:3)
    at onwrite (_stream_writable.js:429:7)
    at DeflateRaw.afterTransform (_stream_transform.js:90:3)
    at Zlib.callback (zlib.js:514:5)

Backtesting

Support for things like:

  • downloading and storing historical data (and updating it with live data real-time),
  • switching to historical data as the event source.

Though order book data is not usually available, many strategies can work without it. Also, it could be recorded and maybe even shared.

Supplement Error message

Make ErrorMessage inherit from StreamMessage and catch all error messages from various WS feeds and push them as proper error messages down the pipe.

Real-time best bid/ask data

I've created the following script to get the best bid/ask data in real-time:

import * as GTT from 'gdax-trading-toolkit';
import { GDAX_WS_FEED, GDAXFeed, GDAXFeedConfig } from 'gdax-trading-toolkit/build/src/exchanges';
import { GDAX_API_URL } from 'gdax-trading-toolkit/build/src/exchanges/gdax/GDAXExchangeAPI';
import { TickerMessage } from 'gdax-trading-toolkit/build/src/core';

const product = 'LTC-EUR';
const logger = GTT.utils.ConsoleLoggerFactory();

const options: GDAXFeedConfig = {
    logger: logger,
    auth: { key: null, secret: null, passphrase: null }, // use public feed
    channels: ['ticker'],
    wsUrl: GDAX_WS_FEED,
    apiUrl: GDAX_API_URL
};

GTT.Factories.GDAX.getSubscribedFeeds(options, [product]).then((feed: GDAXFeed) => {
    GTT.Core.createTickerTrigger(feed, product)
        .setAction((ticker: TickerMessage) => {
            console.log(`Best Bid: ${ticker.bid}`);
            console.log(`Best Ask: ${ticker.ask}`);
        });
});

I was expecting to get the best bid/ask data instantly, as soon as there's a new best bid/ask but that's not happening:
screen shot 2017-10-19 at 11 49 15
Any idea on what could be the issue here?

Browser support

Is it possible to use this library on client-side (browser)?

loadAllOrders() returns 0.0 for the price on pending limit orders

Steps to Recreate:

Option 1:

  1. Run gdaxAPI.loadAllOrders() on an account with pending limit orders
  2. Inspect the results

Option 2:

  1. Run gdaxConsole -O on an account with pending limit orders
  2. Note the price column.

What I expected:

I expected the returned objects to contain a value or both size and price corresponding to the pending limit order

What I experienced:

Only the size contained a valid BigNumber value. price always seems to be Big(0.0).

However, extra.size and extra.price seem to contain the correct values albeit as strings.


gdax-trading-toolkit version 0.1.29

JavaScript heap out of memory

I let the example t002_liveOrderbook.ts run for a few hours and got the below error.

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
1: node::Abort() [/usr/bin/node]
2: 0x1356bec [/usr/bin/node]
3: v8::Utils::ReportOOMFailure(char const*, bool) [/usr/bin/node]
4: v8::internal::V8::FatalProcessOutOfMemory(char const*, bool) [/usr/bin/node]
5: v8::internal::Factory::NewTransitionArray(int) [/usr/bin/node]
6: v8::internal::TransitionArray::Insert(v8::internal::Handlev8::internal::Map, v8::internal::Handlev8::internal::Name, v8::internal::Handlev8::internal::Map, v8::internal::SimpleTransitionFlag) [/usr/bin/node]
7: v8::internal::Map::CopyReplaceDescriptors(v8::internal::Handlev8::internal::Map, v8::internal::Handlev8::internal::DescriptorArray, v8::internal::Handlev8::internal::LayoutDescriptor, v8::internal::TransitionFlag, v8::internal::MaybeHandlev8::internal::Name, char const*, v8::internal::SimpleTransitionFlag) [/usr/bin/node]
8: v8::internal::Map::CopyAddDescriptor(v8::internal::Handlev8::internal::Map, v8::internal::Descriptor*, v8::internal::TransitionFlag) [/usr/bin/node]
9: v8::internal::Map::CopyWithField(v8::internal::Handlev8::internal::Map, v8::internal::Handlev8::internal::Name, v8::internal::Handlev8::internal::FieldType, v8::internal::PropertyAttributes, v8::internal::PropertyConstness, v8::internal::Representation, v8::internal::TransitionFlag) [/usr/bin/node]
10: v8::internal::Map::TransitionToDataProperty(v8::internal::Handlev8::internal::Map, v8::internal::Handlev8::internal::Name, v8::internal::Handlev8::internal::Object, v8::internal::PropertyAttributes, v8::internal::PropertyConstness, v8::internal::Object::StoreFromKeyed) [/usr/bin/node]
11: v8::internal::LookupIterator::PrepareTransitionToDataProperty(v8::internal::Handlev8::internal::JSObject, v8::internal::Handlev8::internal::Object, v8::internal::PropertyAttributes, v8::internal::Object::StoreFromKeyed) [/usr/bin/node]
12: v8::internal::StoreIC::LookupForWrite(v8::internal::LookupIterator*, v8::internal::Handlev8::internal::Object, v8::internal::Object::StoreFromKeyed) [/usr/bin/node]
13: v8::internal::StoreIC::UpdateCaches(v8::internal::LookupIterator*, v8::internal::Handlev8::internal::Object, v8::internal::Object::StoreFromKeyed) [/usr/bin/node]
14: v8::internal::StoreIC::Store(v8::internal::Handlev8::internal::Object, v8::internal::Handlev8::internal::Name, v8::internal::Handlev8::internal::Object, v8::internal::Object::StoreFromKeyed) [/usr/bin/node]
15: v8::internal::KeyedStoreIC::Store(v8::internal::Handlev8::internal::Object, v8::internal::Handlev8::internal::Object, v8::internal::Handlev8::internal::Object) [/usr/bin/node]
16: v8::internal::Runtime_KeyedStoreIC_Miss(int, v8::internal::Object**, v8::internal::Isolate*) [/usr/bin/node]
17: 0x3050d5846fd
Aborted (core dumped)

Market order precision and funds parameter

Hi there,

I recently started to use your toolbox to code my first trading bot on GDAX. This is my first time coding with typescript. I quite enjoy it though and your toolbox is very straighforward to learn :)

My problem is, that as soon as I want to give a more precise market order with more than two decimal places (e.g. 0.024) it will only send with a precision of two decimal places (e.g. 0.02 - the last decimal 4 is lost). I know that the minimum for a limit order is set at 0.01 but I thought there is no restriction with market orders. My function to perform the actual trade looks like this:

function performTrade(side:string, price:BigJS) {   
    let size: BigJS = workingProductAmount;
    
    if(side == 'sell') {
        if(workWithWins) {
            size = balanceProduct.available; 
        }
    
        logger.log('info', `Time to sell ${size}${base}s at current price!`); 
    } else if (side == 'buy') {        
        if(workWithWins) {
            size = balanceEUR.available.div(price);
        }

        logger.log('info', `Time to buy ${size}${base}s at current price!`);   
    }
  
    logger.log('info', `size.toString() ${size.toString()}`);   

    const message: PlaceOrderMessage = {
        type: 'placeOrder',
        productId: product,
        size: size.toString(),
        side: side,
        orderType: 'market',
        time: null
    };   

    trader.executeMessage(message);
}

Also, I have trouble using the funds parameter in PlaceOrderMessage. The market order only works when I specify the size field and no value for funds, but it does not work vice versa. This is why I have to calculate the max amount of buyable BTC based on my current available EUR balance.

I am sure I am doing something wrong here.I would greatly appreciate if someone could point me to the right direction.

Cheers,

Lorenz

Placing GDAX market orders into order book seems to be broken.

So, I'm use a Trader class to place a market order and every attempt at placing a makert order fails. I get this error:

Unable to place order TypeError: Cannot read property 'eq' of null
    at AggregatedLevelWithOrders.addOrder (/Users/adrian/Code/crypto-trader/node_modules/gdax-trading-toolkit/src/lib/BookBuilder.ts:113:24)
    at BookBuilder.add (/Users/adrian/Code/crypto-trader/node_modules/gdax-trading-toolkit/src/lib/BookBuilder.ts:242:20)
    at api.placeOrder.then (/Users/adrian/Code/crypto-trader/node_modules/gdax-trading-toolkit/src/core/Trader.ts:94:31)
    at <anonymous>
    at process._tickDomainCallback (internal/process/next_tick.js:228:7)

The reason for this error is because the price (this.price in the stacktrace) passed into the AggregatedLevelWithOrders is null which is because of this line. The reason why that condition is true, and the price is being set to null is because of this data I'm getting back from the GDAX API once the market order has been placed:

{ id: '0c8e7a83-----------------1abc2d0',
     size: '0.01000000',
     product_id: 'ETH-EUR',
     side: 'sell',
     stp: 'dc',
     type: 'market',
     post_only: false,
     created_at: '2017-11-16T01:51:31.372597Z',
     fill_fees: '0.0000000000000000',
     filled_size: '0.00000000',
     executed_value: '0.0000000000000000',
     status: 'pending',
     settled: false }

As you can see, the execute_value is zero and thus the calculated price is zero. Now, I think this may be a bug in GDAX's API but I'm not sure. Should the GDAX API be returning a value greater than zero or is it expected that the execute_value be zero? Another reason to suspect a bug in the GDAX API is that interface is showing a fill fee of 0.0071 and in the response above, it's zero.

Edit: The order hasn't been filled, only placed so this data would not exist in the response from the request so I think the GDAX API is good. I'm starting to think this is a bug in the trading toolkit.

Actually, this is related to #80. I was getting similar errors but went a couple of steps further debugging.

Calling loadBalances with Poloniex

Hey team,

I am having an problem performing a lookup of balances on Poloniex. I wondered if anyone could take a look here and offer suggestions.

Here is my code, I tried to make it as SMALL as I could for this example:

import * as GTT from 'gdax-trading-toolkit';
import { Balances } from 'gdax-trading-toolkit/build/src/exchanges/AuthenticatedExchangeAPI';

const logger = GTT.utils.ConsoleLoggerFactory({ level: 'info' });
const polo = GTT.Factories.Poloniex.DefaultAPI(logger);

logger.log('info', "key: " + process.env.POLONIEX_KEY);
logger.log('info', "sec: " + process.env.POLONIEX_SECRET);

polo.loadBalances()
    .then( (balances: Balances) => {
        logger.log('info', balances.toString());
    })
    .catch( (err) => {
        logger.log('error', err.message, err);
    });

I open a terminal and call this code like this:

POLONIEX_KEY="MYKEY" POLONIEX_SECRET="MYSECRET" ts-node src/index.ts

Whenever I do this I get back this error:

{ error: 'Invalid API key.' }

The code DOES print/log out the correct key and secret.

I feel like I'm missing something very specific. Does this code work for any of you?

Thanks!

Tutorial one fails to run. SyntaxError: Unexpected identifier

This command works for me.
$ ts-node src/consoles/gdaxConsole.ts --product BTC-USD -t

But when i try to run
$ ts-node tutorials/t001_feeds.ts

I get"
/home/NAME/node_modules/ccxt/ccxt.js:423
let partial = async params => this[methodName] (url, type, uppercaseMethod, params)
^^^^^^

SyntaxError: Unexpected identifier
at createScript (vm.js:56:10)
at Object.runInThisContext (vm.js:97:10)
at Module._compile (module.js:542:28)
at Object.Module._extensions..js (module.js:579:10)
at Module.load (module.js:487:32)
at tryModuleLoad (module.js:446:12)
at Function.Module._load (module.js:438:3)
at Module.require (module.js:497:17)
at require (internal/module.js:20:19)
at Object. (/home/NAME/node_modules/gdax-trading-toolkit/src/exchanges/ccxt/index.ts:15:1)
"

Any ideas as to why this is happening?

Promise vs async await

Looking through your code you return a new promise then just call resolve later on in the function. With typescript, it handles async await natively for you so that you don't have to create your own promises just to resolve them.

Real Time Data

book.on('LiveOrderbook.update', () => {
console.log(printOrderbook(book, 5));
printOrderbookStats(book);
checkBook(book); //my own method which does a bunch of comparisons and sets up a trade
});

Currently I'm using the live order book set up from t002_liveOrderbook.ts. I added the above code into the feed and deleted the code in the snapshot section. This works for a few minutes but then i get this error:

error: A websocket connection to GDAX was established, but
product subscription failed. reason=Socket is not connected. Have you called connect
()? Otherwise the connection may have dropped and is in the process of reconnecting.

After reconnecting it will start printing again except it will be a few second behind, printing old information. I can't figure out how to consistently get real time data. Any help would be appreciated

Connection fails with request timeout expired

I added these three lines to the beginning of build\src\samples\gdaxAuthChannel.js to set the environment variables that are referenced on line 29-31 (keys obscured).

process.env.GDAX_KEY = '*****';
process.env.GDAX_SECRET = '******';
process.env.GDAX_PASSPHRASE = '*****';

Executing the following command:

node build\src\samples\gdaxAuthChannel.js

results in:

2017-12-11T05:47:30.905Z - info: Creating new Websocket connection to wss://ws-feed.gdax.com (authenticated)
2017-12-11T05:47:31.203Z - debug: Connection to wss://ws-feed.gdax.com (authenticated) has been established.
2017-12-11T05:47:31.203Z - debug: Sending message to WS server type=subscribe, 0=BTC-USD, 1=LTC-USD, 0=matches, 1=user, 2=heartbeat, signature=***, key=***, timestamp=1512971251.203, passphrase=***
2017-12-11T05:47:31.314Z - info: error received type=error, time=Mon Dec 11 2017 00:47:31 GMT-0500 (Eastern Standard Time), message=Sorry, you could not be authenticated: Bad Request, cause=request timestamp expired, type=error, message=Sorry, you could not be authenticated: Bad Request, reason=request timestamp expired

They keys are correct, but for some reason it doesn't seem to make a difference. No matter what keys I put in I still get a 'request timestamp expired' error. I also tried setting the environment variables manually to no effect.

Question regarding debugging Authenticated vs. Unauthenticated GDAX requests

TLDR: Can anyone give me a slight bit of direction where it seems my issue is stemming from (the gdax-tt source, my local system setup or the gdax WS API) as I get failed trades when following the tutorial guide and without entering gdax authentication keys but then I get websocket connection closed errors when I do provide my keys manually?

Hi, I'm trying to get my feet wet by testing out the t005_alertTrader.ts tutorial. I'm trying to figure out if I'm running into a gdax-tt source, a local system setup or a gdax WS API issue, as I'm unable to complete a basic test trade with valid api keys. I have tried 2 different api keys I created on gdax, both with full permissions. I have added ENVs via dotenv but I'm unsuccessful completing a basic test trade whether I add my ENVs to the tutorial script or not. I am able to at least connect and get responses from the GDAX WS API when I leave the tutorial script untouched as mentioned in the tutorial's advice of:

"You can set auth: null to just use the defaults, which since you have your GDAX API keys set in the environment, will automatically use those and receive authenticated messages (nice if you want to confim when your trades are filled)."

However, whenever the script sees a market opportunity and attempts to make a trade, it fails, presumably because my ENVs are not actually getting passed like the tutorial says. I get output similar to this:

MacBook-Pro:gdax-tt goheelsgo$ ts-node tutorials/t005_alertTrader.ts
2017-09-26T13:25:53.072Z - info: Creating new Websocket connection to wss://ws-feed.gdax.com 
2017-09-26T13:25:53.090Z - debug: Reconnecting to wss://ws-feed.gdax.com  in 0 seconds...
2017-09-26T13:25:53.090Z - debug: Closing existing socket prior to reconnecting to wss://ws-feed.gdax.com
2017-09-26T13:25:53.331Z - debug: Connection to wss://ws-feed.gdax.com  has been established.
2017-09-26T13:25:53.331Z - debug: Sending {"type":"subscribe","product_ids":["BTC-USD"],"channels":["ticker","heartbeat"]} message to WS server
Price:   3954.500 | Bid:   3954.490 | Ask:   3954.500 | sequence: undefined
Price:   3954.500 | Bid:   3954.490 | Ask:   3954.500 | sequence: 21336971
.
.
.
2017-09-26T13:26:17.957Z - error: Placing order failed type=order, time=null, productId=BTC-USD, orderType=market, side=buy, size=0.005, reason=A GDAX API request failed. Bad Request
(node:6783) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 3): Error: A GDAX API request failed. Bad Request
(node:6783) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Price:   3954.010 | Bid:   3954.000 | Ask:   3954.010 | sequence: 21336983

Now, when i set my ENVs in the tutorial script:

const options: GDAXFeedConfig = {
    logger: logger,
    auth: { 
        key: process.env.GDAX_KEY, 
        secret: process.env.GDAX_SECRET, 
        passphrase: process.env.GDAX_PASSPHRASE 
    }, // use public feed
    channels: ['ticker'],
    wsUrl: GDAX_WS_FEED,
    apiUrl: GDAX_API_URL
};

It appears to pass them in the config options, yet I get a websocket connection closed by external party 1006 error over and over again, presumably due to a timeout?

MacBook-Pro:gdax-tt goheelsgo$ ts-node tutorials/t005_alertTrader.ts
2017-09-26T13:17:53.197Z - info: Creating new Websocket connection to wss://ws-feed.gdax.com (authenticated)
2017-09-26T13:17:53.217Z - debug: Reconnecting to wss://ws-feed.gdax.com (authenticated) in 0 seconds...
2017-09-26T13:17:53.217Z - debug: Closing existing socket prior to reconnecting to wss://ws-feed.gdax.com
2017-09-26T13:17:53.446Z - debug: Connection to wss://ws-feed.gdax.com (authenticated) has been established.
2017-09-26T13:17:53.447Z - debug: Sending {"type":"subscribe","product_ids":["BTC-USD"],"channels":["ticker","heartbeat"],"signature":"<REDACTED>","key":"<REDACTED>","timestamp":"1506431873.447","passphrase":"<REDACTED>"} message to WS server
2017-09-26T13:18:53.219Z - info: The websocket feed to wss://ws-feed.gdax.com (authenticated) has been closed by an external party. We will reconnect in 5 seconds code=1006, reason=
2017-09-26T13:18:53.220Z - debug: Reconnecting to wss://ws-feed.gdax.com (authenticated) in 5 seconds...
2017-09-26T13:18:58.364Z - debug: Connection to wss://ws-feed.gdax.com (authenticated) has been established.
2017-09-26T13:18:58.365Z - debug: Resubscribing to BTC-USD...
2017-09-26T13:18:58.365Z - debug: Sending {"type":"subscribe","product_ids":["BTC-USD"],"channels":["ticker","heartbeat"],"signature":"<REDACTED>","key":"<REDACTED>","timestamp":"1506431938.365","passphrase":"<REDACTED>"} message to WS server
2017-09-26T13:18:58.366Z - debug: Sending {"type":"subscribe","product_ids":["BTC-USD"],"channels":["ticker","heartbeat"],"signature":"<REDACTED>","key":"<REDACTED>","timestamp":"1506431938.366","passphrase":"<REDACTED>"} message to WS server
2017-09-26T13:18:58.367Z - debug: Reconnection to BTC-USD successful
2017-09-26T13:19:57.911Z - info: The websocket feed to wss://ws-feed.gdax.com (authenticated) has been closed by an external party. We will reconnect in 5 seconds code=1006, reason=

The trade I'm attempting to make is around $15-20 and I've got $50 in my GDAX in USD, so I'd think I wouldn't have any issue with minimums. I'm a bit at a loss currently as Node is not my forte--can anyone give me a bit of direction where it seems my issue is stemming from?

MacBook-Pro:gdax-tt goheelsgo$ ts-node -v
ts-node v3.3.0
node v8.4.0
typescript v2.5.2

how to pipe the feed stream

I am trying to just do a simple pipe to process.stdout stream.

GTT.Factories.GDAX.FeedFactory(logger, products).then(function (feed) {
feed.pipe(process.stdout);
});

What am I doing wrong, I receive error: The websocket feed to wss://ws-feed.gdax.com has reported an error. If necessary, we will reconnect. after every update received from gdax.

My contributions are missing

Heh, thought I'd point out that for some reason the contribution I made isn't showing up.
Reference: ##21

Not a huge issue obviously.

yarn test fails with compilation error: 'price' does not exist in type 'StopOrder'.

yarn test

$ yarn run build
$ tsc -d -p .
src/core/HFTFilter.ts(43,13): error TS6133: 'logger' is declared but its value is never read.
src/core/MessageQueue.ts(77,13): error TS6133: 'messageListener' is declared but its value is never read.
src/exchanges/gdax/GDAXExchangeAPI.ts(219,21): error TS2322: Type '{ type: "stop"; product_id: string; side: "buy" | "sell"; size: string; price: string; funds: str...' is not assignable to type 'OrderParams'.
  Object literal may only specify known properties, and 'price' does not exist in type 'StopOrder'.
src/lib/BigArray.ts(80,5): error TS4053: Return type of public method from exported class has or is using name 'BigNumber.BigNumber' from external module "/home/vish/new-work/bitcoin/gdax/gdax-tt/node_modules/@types/bignumber.js/index" but cannot be named.
src/lib/BigArray.ts(91,5): error TS4053: Return type of public method from exported class has or is using name 'BigNumber.BigNumber' from external module "/home/vish/new-work/bitcoin/gdax/gdax-tt/node_modules/@types/bignumber.js/index" but cannot be named.
src/lib/OrderbookUtils.ts(47,12): error TS4050: Return type of public static method from exported class has or is using name 'BigNumber.BigNumber' from external module "/home/vish/new-work/bitcoin/gdax/gdax-tt/node_modules/@types/bignumber.js/index" but cannot be named.
src/lib/OrderbookUtils.ts(253,5): error TS4053: Return type of public method from exported class has or is using name 'BigNumber.BigNumber' from external module "/home/vish/new-work/bitcoin/gdax/gdax-tt/node_modules/@types/bignumber.js/index" but cannot be named.
src/lib/OrderbookUtils.ts(263,5): error TS4053: Return type of public method from exported class has or is using name 'BigNumber.BigNumber' from external module "/home/vish/new-work/bitcoin/gdax/gdax-tt/node_modules/@types/bignumber.js/index" but cannot be named.
src/lib/StreamCopier.ts(28,13): error TS6133: 'feed' is declared but its value is never read.
src/server/DataFeed.ts(38,5): error TS6133: 'dataFeed' is declared but its value is never read.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

I'm running on node v8.9.2, but I see the same error with other node versions. Other packages:
yarn list gdax typescript ts-node

yarn list v1.3.2
warning Filtering by arguments is deprecated. Please use the pattern option instead.
├─ [email protected]
├─ [email protected]
├─ [email protected]
│  └─ [email protected]
└─ [email protected]

Trader.order-placed event not fired?

It looks like the Trader.order-placed event is not being fired. Here's my script:

import { ConsoleLoggerFactory } from 'gdax-trading-toolkit/build/src/utils/Logger';
import { getSubscribedFeeds } from 'gdax-trading-toolkit/build/src/factories/gdaxFactories';
import { GDAXFeed } from 'gdax-trading-toolkit/build/src/exchanges/gdax/GDAXFeed';
import { Trader, TraderConfig } from 'gdax-trading-toolkit/build/src/core/Trader';
import { LiveOrder } from 'gdax-trading-toolkit/build/src/lib/Orderbook';
import { PlaceOrderMessage, TradeExecutedMessage, TradeFinalizedMessage } from 'gdax-trading-toolkit/build/src/core/Messages';

const auth = {
    key: 'xxx',
    secret: 'xxx',
    passphrase: 'xxx'
};
const logger = ConsoleLoggerFactory();
const product = 'LTC-EUR';

function orderMessage(side: string, price: string) {
    return {
        time: null,
        type: 'placeOrder',
        productId: product,
        size: '1',
        price: price,
        side: side,
        orderType: 'limit',
        postOnly: true
    } as PlaceOrderMessage;
}

getSubscribedFeeds({ auth: auth, logger: logger }, [product]).then((feed: GDAXFeed) => {
    const traderConfig: TraderConfig = {
        logger: logger,
        productId: product,
        exchangeAPI: feed.authenticatedAPI,
        fitOrders: false
    };
    const trader = new Trader(traderConfig);

    trader.on('Trader.order-placed', (msg: LiveOrder) => {
        logger.log('info', 'Order placed', JSON.stringify(msg));
    });

    trader.on('Trader.trade-executed', (msg: TradeExecutedMessage) => {
        logger.log('info', 'Trade executed', JSON.stringify(msg));
    });

    trader.on('Trader.trade-finalized', (msg: TradeFinalizedMessage) => {
        logger.log('info', 'Order complete', JSON.stringify(msg));
    });

    trader.on('Trader.my-orders-cancelled', (ids: string[]) => {
        logger.log('info', `${ids.length} orders cancelled`);
    });

    trader.on('error', (err: Error) => {
        logger.log('error', 'Error cancelling orders', err);
    });

    feed.pipe(trader);

    // Send the order once the feed has initialised
    feed.once('snapshot', () => {
        const order = orderMessage('buy', '54.42');
        trader.executeMessage(order);
    });
});

Here's my log after running the script:

2017-11-15T14:41:55.517Z - info: Creating new Websocket connection to wss://ws-feed.gdax.com (authenticated)
2017-11-15T14:41:56.284Z - debug: Connection to wss://ws-feed.gdax.com (authenticated) has been established.
2017-11-15T14:41:56.285Z - debug: Sending message to WS server type=subscribe, 0=LTC-EUR, 0=level2, 1=matches, 2=ticker, 3=user, 4=heartbeat, signature=***, key=***, timestamp=1510756916.285, passphrase=***
2017-11-15T14:41:56.718Z - debug: GDAX Feed subscriptions confirmed type=subscriptions, name=level2, 0=LTC-EUR, name=matches, 0=LTC-EUR, name=ticker, 0=LTC-EUR, name=user, 0=LTC-EUR, name=heartbeat, 0=LTC-EUR

I can see the order in GDAX but there's no info: Order placed... log message.

I'm using gtt 0.2.0 and node 8.9.1

Handling for CCXT errors

Currently, the CCXT exchange connector has no way of communicating if a method failed or what caused the failure. For example, in the loadProducts() method, if the network request fails, [] is returned without any indication to the caller why the request failed. https://github.com/coinbase/gdax-tt/blob/master/src/exchanges/ccxt/index.ts#L173

In other places, the error is logged to the Logger but null or [] is returned as if the request was successful.


I propose either rejecting the promise with an Error explaining exactly what went wrong or returning some kind of result data type that can indicate the status of the request.

I'd be happy to work on this implementation myself and put in a PR, but I want to know what approach the maintainers would like to go with before doing anything.

Expose all relevant classes

Some classes (e.g. GDAXExchangeAPI) aren't exported in the main GTT tree and so need to be imported using the library folder structure which is a bit yucky.

BUG: Stop orders with a price are submitted as immediate market orders

GDAX API supports a price field for stop orders, but GDAXExchangeAPI#placeOrder() is ignoring this field. This results in submitting the stop order as a market order (incorrectly).

Steps to Recreate:

Issue a stop order using GDAXExchangeAPI#placeOrder()

gdax.placeOrder({
  orderType: 'stop',
  productId: 'ETH-USD'
  side: 'buy',
  size: '0.01',
  price: '1500.00', // NOTE: high price
  funds: '15.00'
});

What I expected:

I expected to see a stop order placed that waits for the price of ETH-USD to hit 1500.00 before converting it to a market order.

What I experienced:

An immediate market order was placed at the current price.


GDAX API explains the differences in parameters between submitted market and stop orders:
https://docs.gdax.com/#place-a-new-order


Pull-request with a fix coming soon... boom!

Type imports

I'm pretty new to typescript. I haven't figured out how to import the types like GDAXFeed without doing import { GDAXFeed } from "gdax-trading-toolkit/build/src/exchanges" both Atom (with typescript package) and ts-node say Cannot find name 'GDAXFeed'. if I just use import * as GTT from 'gdax-trading-toolkit'. Does there need to be a @types/gdax-trading-toolkit package?

For brevity, import statements will be omitted from tutorial source snippets. If you’re using a TypeScript-friendly IDE, type definition imports should be added automatically. If you’re using standard Javascript, the GTT is usually the only import you’ll need.

gdaxConsole error: 'price' does not exist in type 'StopOrder'

getting the following error when running ts-node src/consoles/gdaxConsole.ts --product BTC-USD -t

/usr/local/n/lib/node_modules/ts-node/src/index.ts:307
        throw new TSError(formatDiagnostics(diagnosticList, cwd, ts, lineOffset))
              ^
TSError: ⨯ Unable to compile TypeScript
src/exchanges/gdax/GDAXExchangeAPI.ts (219,21): Type '{ type: "stop"; product_id: string; side: "buy" | "sell"; size: string; price: string; funds: str...' is not assignable to type 'OrderParams'.
  Object literal may only specify known properties, and 'price' does not exist in type 'StopOrder'. (2322)
    at getOutput (/usr/local/n/lib/node_modules/ts-node/src/index.ts:307:15)
    at /usr/local/n/lib/node_modules/ts-node/src/index.ts:336:16
    at Object.compile (/usr/local/n/lib/node_modules/ts-node/src/index.ts:498:11)
    at Module.m._compile (/usr/local/n/lib/node_modules/ts-node/src/index.ts:392:43)
    at Module._extensions..js (module.js:623:10)
    at Object.require.extensions.(anonymous function) [as .ts] (/usr/local/n/lib/node_modules/ts-node/src/index.ts:395:12)
    at Module.load (module.js:531:32)
    at tryModuleLoad (module.js:494:12)
    at Function.Module._load (module.js:486:3)
    at Module.require (module.js:556:17)

Deadlines

I'm not sure about other exchanges, but Poloniex seems to use crude / rude exponential backoff when they can't secure the resources for a request, and many of their responses come as much as two minutes after the request was sent. Waiting that long for a response is unacceptable, so I suggest setting a reasonable deadline for requests (e.g. 3s) after which they could be retried or abandoned (https://visionmedia.github.io/superagent/#timeouts).

Create the gtt-ui project

It is currently referenced by the documentation, but it does not exist anywhere. Creating this issue as a reference to its status that the documentation can link to.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.