Giter VIP home page Giter VIP logo

peterszombati / xapi-node Goto Github PK

View Code? Open in Web Editor NEW
56.0 9.0 19.0 1.1 MB

xStation5 Trading API for NodeJS/JS

Home Page: https://peterszombati.github.io/xapi-node/

License: Other

TypeScript 99.41% JavaScript 0.59%
nodejs typescript xstation5 websocket xapi trading trading-api xtb xopenhub forex exchange-api forex-api xopenhub-api xtb-api xstation-api x-trade-brokers forex-trading forex-data bfbcapital xstation

xapi-node's Introduction

Logo

xapi-node

This project makes it possible to get data from Forex market, execute market or limit order with NodeJS/JS through WebSocket connection

This module may can be used for X-Trade Brokers xStation5 accounts

WebSocket protocol description: https://peterszombati.github.io/xapi-node/

This module is usable on Front-end too.

Getting started

1. Install via npm

npm i xapi-node

2. Example usage

Authentication

// TypeScript
import XAPI from 'xapi-node'

const x = new XAPI({
    accountId: '(xStation5) accountID',
    password: '(xStation5) password',
    type: 'real' // or demo
})

(async () => {
  await x.connect()
  console.log('Connection is ready')
  x.disconnect().then(() => console.log('Disconnected'))
})().catch((e) => {
  console.error(e)
})

Authentication only for XTB accounts

// TypeScript
import XAPI from 'xapi-node'

const x = new XAPI({
    accountId: '(xStation5) accountID',
    password: '(xStation5) password',
    host: 'ws.xtb.com', // only for XTB accounts
    type: 'real' // or demo
})

(async () => {
  await x.connect()
  x.disconnect().then(() => console.log('Disconnected'))
})().catch((e) => {
  console.error(e)
})

placing buy limit on BITCOIN [CFD]

x.Socket.send.tradeTransaction({
    cmd: CMD_FIELD.BUY_LIMIT,
    customComment: null,
    expiration: new Date().getTime() + 60000 * 60 * 24 * 365,
    offset: 0,
    order: 0,
    price: 100,
    sl: 0,
    symbol: 'BITCOIN',
    tp: 8000,
    type: TYPE_FIELD.OPEN,
    volume: 10
}).then(({order}) => {
    console.log('Success ' + order)
}).catch(e => {
    console.error('Failed')
    console.error(e)
})

placing buy limit on US30 (Dow Jones Industrial Average)

x.Socket.send.tradeTransaction({
    cmd: CMD_FIELD.BUY_LIMIT,
    customComment: null,
    expiration: new Date().getTime() + 60000 * 60 * 24 * 365,
    offset: 0,
    order: 0,
    price: 21900,
    sl: 0,
    symbol: 'US30',
    tp: 26500,
    type: TYPE_FIELD.OPEN,
    volume: 0.2
}).then(({order}) => {
    console.log('Success ' + order)
}).catch(e => {
    console.error('Failed')
    console.error(e)
})

get live EURUSD price data changing

x.Stream.listen.getTickPrices((data) => {
    console.log(data.symbol + ': ' + data.ask + ' | ' + data.askVolume + ' volume | ' + data.level + ' level' )
})

(async () => {
  await x.connect()
  x.Stream.subscribe.getTickPrices('EURUSD')
    .catch(() => { console.error('subscribe for EURUSD failed')})
})()

/* output
EURUSD: 1.10912 | 500000 volume | 0 level
EURUSD: 1.10913 | 1000000 volume | 1 level
EURUSD: 1.10916 | 1000000 volume | 2 level
EURUSD: 1.10922 | 3000000 volume | 3 level
EURUSD: 1.10931 | 3500000 volume | 4 level
...
*/

get EURUSD M1 price history

(async () => {
  await x.connect()
  x.getPriceHistory({
    symbol:'EURUSD',
    period: PERIOD_FIELD.PERIOD_M1
  }).then(({candles, digits}) => {
    console.log(candles.length)
    console.log(candles[0])
    console.log('digits = ' + digits)
  })
})()

market buy EURUSD (1.0 lot / 100000 EUR)

(async () => {
  await x.connect()
  x.Socket.send.tradeTransaction({
    cmd: CMD_FIELD.BUY,
    customComment: null,
    expiration: x.serverTime + 5000,
    offset: 0,
    order: 0,
    price: 1,
    symbol: 'EURUSD',
    tp: 0,
    sl: 0,
    type: TYPE_FIELD.OPEN,
    volume: 1
  }).then(({order}) => {
    console.log('Success ' + order)
  }).catch(e => {
    console.error('Failed')
    console.error(e)
  })
})()

modify open position (for example set new stop loss)

(async () => {
  await x.connect()
  x.Socket.send.tradeTransaction({
    order: 1234, // position number you can find it in (x.positions)
    type: TYPE_FIELD.MODIFY,
    sl: 1.05, // new stop loss level
  }).then(({order}) => {
    console.log('Success ' + order)
  }).catch(e => {
    console.error('Failed')
    console.error(e)
  })
})()

How to use logger

import {Logger,XAPI} from 'xapi-node'

const l = new Logger()
l.on({
  type: 'debug',
  callback: data => console.log(data)
})
l.on({
  type: 'transaction',
  callback: data => console.log(data)
})
l.on({
  type: 'error',
  callback: data => console.log(data)
})
l.on({
  type: 'info',
  callback: data => console.log(data)
})

const x = new XAPI({
  accountId: '(xStation5) accountID',
  password: '(xStation5) password',
  type: 'real' // or demo
}, l)

xapi-node's People

Contributors

matb85 avatar peterszombati avatar peterszombati-bvtech-io 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

xapi-node's Issues

How to get current trades

Hi,
I cannot find method to get all current open and pending trades.

I've thought that this is getTradesHistory but it show closed records, am I right?

getCandles listener never gets triggered

I've tried to get the realtime candles, even waited more the one minute as the official docs says and apparently the listener never gets called, see the code from below:

const x = new XAPI.default({
    accountId: <MY-ACCOUNT-ID>,
    password: <MY-PASSWORD>,
    type: 'demo' // or demo
});

x.connect();

x.onReady(async () => {
    console.log('Connection is ready');

    x.Stream.listen.getCandles((data) => {
        // THIS IS NEVER REACHED
        console.log("GOT DATA", data);
    });

    x.Stream.subscribe.getCandles('BITCOIN')
        .catch(() => { console.error('subscribe for BITCOIN failed')});

})

Am I doing something wrong ?

PS: getTickPrices works as expected

[REAL ACCOUNT] EX017 - You are trying to login using the account from a different platform

First, I want to thank you very much for this repository, it has helped me a lot!

I created an application that uses this module, and in DEMO it works perfectly.

However, when you put the actual data, I get this return:

CODE:

const x = new XAPI({
    accountId: '.....',
    password: '...',
    type: 'real',
  });

RETURN:

{
 code: 'EX017',
 explain: 'You are trying to login using the account from a different platform'
}

getCommissionDef

If I want to get the exchange rate from the input symbol to my account currency(different from USD)
getCommissionDef always get as response commission = 0 and rateOfExchange = 1, no matter what symbol or volume I input.
Is the same on https://playground.xapi.pro/login .
So for sure is not a bug of xapi-node, but the method doesn't seems to work as expected.

x.Stream.subscribe.getCandles bug (caused by xOpenHub server side logic)

x.Stream.subscribe.getCandles doesn't working if you didn't do a price history request for specific symbol
example with BITCOIN:

x.Stream.subscribe.getCandles('BITCOIN')
        .catch(() => { console.error('subscribe for BITCOIN failed')});

It won't work.
You have to do a request to BITCOIN price history then subscribe for candles
example with BITCOIN:

x.getPriceHistory({
  symbol: 'BITCOIN',
  period: PERIOD_FIELD.PERIOD_M1,
  ticks: -1
})

x.Stream.subscribe.getCandles('BITCOIN')
        .catch(() => { console.error('subscribe for BITCOIN failed')});

Stream commands not working in demo

I'm not sure if there are restrictions with the stream commands in demo accounts, but I'm unable to make it work. This is my code:

const x = new XAPI.default({
    accountId: <MY-ACCOUNT-ID>,
    password: <MY-PASSWORD>,
    type: 'demo' // or demo
});

x.connect();

x.onReady(async () => {
    console.log('Connection is ready');

    x.Stream.listen.getTickPrices((data) => {
        console.log(data.symbol + ': ' + data.ask + ' | ' + data.askVolume + ' volume | ' + data.level + ' level' );
    });

    x.Stream.subscribe.getTickPrices('EURUSD')
        .catch(() => { console.error('subscribe for EURUSD failed')});

    const r = await x.Socket.send.getSymbol('EURUSD');
    console.log('response');
    console.log(r.returnData);
})

And the output is this:

Connection is ready
response
{
  symbol: 'EURUSD',
  currency: 'EUR',
  categoryName: 'FX',
  currencyProfit: 'USD',
  quoteId: 5,
  quoteIdCross: 4,
  marginMode: 101,
  profitMode: 5,
  pipsPrecision: 4,
  contractSize: 100000,
  exemode: 1,
  time: 1615582799825,
  expiration: null,
  stopsLevel: 0,
  precision: 5,
  swapType: 1,
  stepRuleId: 5,
  type: 971,
  instantMaxVolume: 2147483647,
  groupName: 'Major',
  description: 'Euro to American Dollar',
  longOnly: false,
  trailingEnabled: true,
  marginHedgedStrong: false,
  swapEnable: true,
  percentage: 100,
  bid: 1.19602,
  ask: 1.1961,
  high: 1.19881,
  low: 1.19096,
  lotMin: 0.01,
  lotMax: 100,
  lotStep: 0.01,
  tickSize: 0.00001,
  tickValue: 1,
  swapLong: -5.527,
  swapShort: -1.104,
  leverage: 3.33,
  spreadRaw: 0.00008,
  spreadTable: 0.8,
  starting: null,
  swap_rollover3days: 0,
  marginMaintenance: 0,
  marginHedged: 0,
  initialMargin: 0,
  timeString: 'Fri Mar 12 21:59:59 CET 2021',
  shortSelling: true,
  currencyPair: true
}

As you can see, I can only see the response from the getSymbol (socket) request, but there are no signs from the getTickPrices subscription. Am I missing something?

Missing Documentation for getPriceHistory

Hey,

seems like there´s no documentation for the "getPriceHistory()" response type.
You´ll get a two-dimensional number array (number[][]) for the candles but I could not find any reference to what the array values represent.

I checked your code and found the candle data is:
Index 0: timestamp
Index 1: open
Index 2: close
Index 3: low
Index 4: high
Index 5: volume

Maybe even returning an array of candle objects instead of the number array would be a great move.

How to get notice when position is closed?

I've started using your wrapper to XTB. I know how to open position, but don't know how to get notice when position is closed? If you can give me short example I would be gratefull.

issue with node 18

In package.json, have installed xapi-node version 2.5.5, on node 18.10.0
I run the command: npm start and got this issue:

...\node_modules\xapi-node\build\core\Socket\SocketConnection.js:147
if (retries > 0 && e.reason.code !== Enum_1.errorCode.XAPINODE_1 && e.reason.code !== Enum_1.errorCode.BE005) {
^

TypeError: Cannot read properties of undefined (reading 'code')
at ...\node_modules\xapi-node\build\core\Socket\SocketConnection.js:147:41

Unable to destroy instance when login fails

Sorry to bother again but I'm having trouble with accounts which fail to login
(e.g. expired demo accounts or when entered wrong password).

They try to reconnect all the time even when I call disconnect method.
On the contrary, when I call disconnect method after failed login I keep getting uncaught exception
'Not logged - logout' (BE103)

I have a doubt that this may lead to memory leaks.

Is there a way to disable tryReconnect or stop reconnecting and close the socket after calling disconnect even when authentication was unsuccessful?

parseStack.js:10 Uncaught ReferenceError: process is not defined

If before things were warning during compile, you've actually managed to introduce node specific commands (backend) into frontend and now I've got the following error:

parseStack.js:10 Uncaught ReferenceError: process is not defined
    at Object.20617 (parseStack.js:10)
    at __webpack_require__ (bootstrap:19)
    at Object.58726 (parseError.js:5)
    at __webpack_require__ (bootstrap:19)
    at Object.3015 (index.js:7)
    at __webpack_require__ (bootstrap:19)
    **at Object.66665 (XAPI.js:5)**
    at __webpack_require__ (bootstrap:19)
    at Object.90304 (index.js:4)
    at __webpack_require__ (bootstrap:19)

Found the issue: it's caused by that other product of yours Logger4 and found where you're using process:

Anyway, we don't have process in browsers :(

getBalance()

Hi,
final question I hope,
How do I getBalance? I've set up the same callback as for trades but nothing ever comes through.
is there a command to request the info to the callback?

Oh I see I get a balance if there are trades going. but not before?

thanks

indended to be used with logger4?

Hello, nice package!

when I connect it with my account I get this message
[xapi-node]: Logger path is not defined

Should you update the docs to explain why this happen? and if one is expected to use your logger package with this?

Replace dependecy Logger4 with Winston

Hi,

Your library works perfect for backend and also for frontend apps, however after upgrading from Angular 11 to Angular 12 (which underneath upgraded from Webpack 4 to 5) the application doesn't compile anymore because of the usage of "fs" and "path" which obviously are not supported by browsers.

Initially I wanted to do myself a PR with the upgrade (and I'm still willing to help) but once I've cloned your repo the 1st thing that hit was the setup with the missing sensitive/sensitive.json file for obvious security reasons; I've fixed that no pb.
However I can't test it, because in your package.json you have under scripts section:

"test": "echo \"Error: no test specified\" && exit 1"

And this is where I'm blocked currently, since I've only found a way to launch mocha for the sandbox/sandbox.ts file only.
Do you think that it would be possible to fix that in your repo ?
Also, out of curiosity why do you chai as a dependency ? are you using mocha or chai since I don't see any usage of it ?

This is Winston.

Issue with closing STC positions on XTB

Hi there, the issue only occur when trying to close STC position doesn't happen when trying to close CRT position. I'm using XTB demo account.

code:

  try {
    await x.Socket.send
      .tradeTransaction({
        order: <POSITION_ID>,
        symbol: "RBLX.US",
        type: TYPE_FIELD.CLOSE,
        price: 0,
        volume: 1,
      })
      .then(() => {
        console.log("done");
      });
  } catch (err) {
    logError(err);
  }

also here is error dump:

 JsonError
    at Socket.sendCommand (C:\Users\mazep\Desktop\Projects\TS\TradeBot\node_modules\xapi-node\build\core\Socket\SocketConnection.js:60:23)
    at C:\Users\mazep\Desktop\Projects\TS\TradeBot\node_modules\xapi-node\build\core\Socket\Socket.js:119:33
    at new Promise (<anonymous>)
    at Object.tradeTransaction (C:\Users\mazep\Desktop\Projects\TS\TradeBot\node_modules\xapi-node\build\core\Socket\Socket.js:103:24)
    at Object.g2 (C:\Users\mazep\Desktop\Projects\TS\TradeBot\dist\index.js:93:14) {
  params: {
    reason: { code: 'BE11', explain: 'Position not found (#<POSITION_ID>)' },
    transaction: {
      command: 'tradeTransaction',
      type: 'Socket',
      request: [Object],
      response: [Object],
      transactionId: '164089816808500060',
      createdAt: [Time],
      status: 3,
      transactionPromise: [Object],
      urgent: true,
      stack: 'Error\n' +
        '    at Socket.sendCommand (C:\\Users\\mazep\\Desktop\\Projects\\TS\\TradeBot\\node_modules\\xapi-node\\build\\core\\Socket\\SocketConnection.js:60:23)\n' +
        '    at C:\\Users\\mazep\\Desktop\\Projects\\TS\\TradeBot\\node_modules\\xapi-node\\build\\core\\Socket\\Socket.js:119:33\n' +
        '    at new Promise (<anonymous>)\n' +
        '    at Object.tradeTransaction (C:\\Users\\mazep\\Desktop\\Projects\\TS\\TradeBot\\node_modules\\xapi-node\\build\\core\\Socket\\Socket.js:103:24)\n' +
        '    at Object.g2 (C:\\Users\\mazep\\Desktop\\Projects\\TS\\TradeBot\\dist\\index.js:93:14)'
    }
  }
}

bfb connection details

Hi Peter,

xtb won't accept Australian clients. do you know the bfb server name(s) for auth/connect?

thanks !

XAPI.onReady() method being called endlessly for no reason

Hi there!

I have noticed strange behavior while using the .onReady method - it gets called randomly, twice each time.

In the example below, this.fetcher is an instance of XAPI reused in another class:

connectToMarket = (): void => {
		this.fetcher.connect();

		this.fetcher.onReady(() => {
			let now = new Date();
			console.log(
				'Fetcher is connected and ready',
				now.getHours(),
				':',
				now.getMinutes(),
				'.',
				now.getSeconds()
			);
		});
	};

This gives me an output:

Fetcher is connected and ready 18 : 49 . 31
Fetcher is connected and ready 18 : 49 . 31
Fetcher is connected and ready 18 : 49 . 44
Fetcher is connected and ready 18 : 49 . 44
Fetcher is connected and ready 18 : 50 . 35
Fetcher is connected and ready 18 : 50 . 35
Fetcher is connected and ready 18 : 51 . 28
Fetcher is connected and ready 18 : 51 . 28
Fetcher is connected and ready 18 : 52 . 19
Fetcher is connected and ready 18 : 52 . 19
Fetcher is connected and ready 18 : 53 . 13
Fetcher is connected and ready 18 : 53 . 13

Any idea what can be causing that?

[feature] getAllSymbols

Hi,
How to get the list of symbols?
On the documentation, the "getAllSymbols" method exists.

x.getPriceHistory Data limit potentially exceeded

Getting price history for period M1 and startUtc of January 2020 fails since the request rate exceeds 50000.
I checked the XAPI.getPriceHistory() function and it looks kind of strange to me.
Passing both, "ticks" and "startUtc", will always result in one of them being ignored since chartRangeRequest does not use the startUtc argument and getChartLastRequest does not use the ticks variable.

Is there any reason to use getChartLastRequest at all?
I cannot see any so if you don´t either I could raise a pull request to always use getChartRangeRequest.

Invalid parameters when close or delete position

Hello,

I can not close a position after open it :

  x.positions.map((pos) => {
    x.Socket.send
      .tradeTransaction({
        order: pos.order,
        type: TYPE_FIELD.DELETE,
      })
      .then(console.log)
      .catch(console.error);
  });

I have this error :

{
  reason: { code: 'EX000', explain: 'Invalid parameters' },
  transaction: {
    command: 'tradeTransaction',
    type: 'Socket',
    request: {
      json: '{"command":"tradeTransaction","arguments":{"tradeTransInfo":{"customComment":"x163211469666300080","order":304233558,"type":4}},"customTag":"tradeTransaction_163211469666300080"}',
      arguments: [Object],
      sent: [Time]
    },
    response: { status: false, received: [Time], json: [Object] },
    transactionId: '163211469666300080',
    createdAt: Time { unit: [Array], UTCTimestamp: 1632114696663 },
    status: 3,
    transactionPromise: { resolve: null, reject: null },
    urgent: true
  }
}

I have the same error with CLOSE type.

Thank you for you'r help 🙏

Tick prices showing up multiple times

I seem to always get the tick prices 7 times in a row. Timestamp, ask, bid, volume and everything is exactly the same.
Registered one listener to the tickPrice subscription.

To make sure it´s an issue I wrote a little connector for the API myself and there I get the data just once.

{"symbol":"EURUSD","ask":1.18726,"bid":1.18717,"high":1.18745,"low":1.18702,"askVolume":200000,"bidVolume":200000,"timestamp":1617750266568,"level":0,"quoteId":5,"spreadTable":0.9,"spreadRaw":0.00009} {"symbol":"EURUSD","ask":1.18726,"bid":1.18717,"high":1.18745,"low":1.18702,"askVolume":200000,"bidVolume":200000,"timestamp":1617750266568,"level":0,"quoteId":5,"spreadTable":0.9,"spreadRaw":0.00009} {"symbol":"EURUSD","ask":1.18726,"bid":1.18717,"high":1.18745,"low":1.18702,"askVolume":200000,"bidVolume":200000,"timestamp":1617750266568,"level":0,"quoteId":5,"spreadTable":0.9,"spreadRaw":0.00009} {"symbol":"EURUSD","ask":1.18726,"bid":1.18717,"high":1.18745,"low":1.18702,"askVolume":200000,"bidVolume":200000,"timestamp":1617750266568,"level":0,"quoteId":5,"spreadTable":0.9,"spreadRaw":0.00009} {"symbol":"EURUSD","ask":1.18726,"bid":1.18717,"high":1.18745,"low":1.18702,"askVolume":200000,"bidVolume":200000,"timestamp":1617750266568,"level":0,"quoteId":5,"spreadTable":0.9,"spreadRaw":0.00009} {"symbol":"EURUSD","ask":1.18726,"bid":1.18717,"high":1.18745,"low":1.18702,"askVolume":200000,"bidVolume":200000,"timestamp":1617750266568,"level":0,"quoteId":5,"spreadTable":0.9,"spreadRaw":0.00009} {"symbol":"EURUSD","ask":1.18726,"bid":1.18717,"high":1.18745,"low":1.18702,"askVolume":200000,"bidVolume":200000,"timestamp":1617750266568,"level":0,"quoteId":5,"spreadTable":0.9,"spreadRaw":0.00009} {"symbol":"EURUSD","ask":1.18725,"bid":1.18716,"high":1.18745,"low":1.18702,"askVolume":200000,"bidVolume":300000,"timestamp":1617750266742,"level":0,"quoteId":5,"spreadTable":0.9,"spreadRaw":0.00009} {"symbol":"EURUSD","ask":1.18725,"bid":1.18716,"high":1.18745,"low":1.18702,"askVolume":200000,"bidVolume":300000,"timestamp":1617750266742,"level":0,"quoteId":5,"spreadTable":0.9,"spreadRaw":0.00009} {"symbol":"EURUSD","ask":1.18725,"bid":1.18716,"high":1.18745,"low":1.18702,"askVolume":200000,"bidVolume":300000,"timestamp":1617750266742,"level":0,"quoteId":5,"spreadTable":0.9,"spreadRaw":0.00009} {"symbol":"EURUSD","ask":1.18725,"bid":1.18716,"high":1.18745,"low":1.18702,"askVolume":200000,"bidVolume":300000,"timestamp":1617750266742,"level":0,"quoteId":5,"spreadTable":0.9,"spreadRaw":0.00009} {"symbol":"EURUSD","ask":1.18725,"bid":1.18716,"high":1.18745,"low":1.18702,"askVolume":200000,"bidVolume":300000,"timestamp":1617750266742,"level":0,"quoteId":5,"spreadTable":0.9,"spreadRaw":0.00009} {"symbol":"EURUSD","ask":1.18725,"bid":1.18716,"high":1.18745,"low":1.18702,"askVolume":200000,"bidVolume":300000,"timestamp":1617750266742,"level":0,"quoteId":5,"spreadTable":0.9,"spreadRaw":0.00009} {"symbol":"EURUSD","ask":1.18725,"bid":1.18716,"high":1.18745,"low":1.18702,"askVolume":200000,"bidVolume":300000,"timestamp":1617750266742,"level":0,"quoteId":5,"spreadTable":0.9,"spreadRaw":0.00009} {"symbol":"EURUSD","ask":1.18725,"bid":1.18716,"high":1.18745,"low":1.18702,"askVolume":200000,"bidVolume":299000,"timestamp":1617750266993,"level":0,"quoteId":5,"spreadTable":0.9,"spreadRaw":0.00009} {"symbol":"EURUSD","ask":1.18725,"bid":1.18716,"high":1.18745,"low":1.18702,"askVolume":200000,"bidVolume":299000,"timestamp":1617750266993,"level":0,"quoteId":5,"spreadTable":0.9,"spreadRaw":0.00009} {"symbol":"EURUSD","ask":1.18725,"bid":1.18716,"high":1.18745,"low":1.18702,"askVolume":200000,"bidVolume":299000,"timestamp":1617750266993,"level":0,"quoteId":5,"spreadTable":0.9,"spreadRaw":0.00009} {"symbol":"EURUSD","ask":1.18725,"bid":1.18716,"high":1.18745,"low":1.18702,"askVolume":200000,"bidVolume":299000,"timestamp":1617750266993,"level":0,"quoteId":5,"spreadTable":0.9,"spreadRaw":0.00009} {"symbol":"EURUSD","ask":1.18725,"bid":1.18716,"high":1.18745,"low":1.18702,"askVolume":200000,"bidVolume":299000,"timestamp":1617750266993,"level":0,"quoteId":5,"spreadTable":0.9,"spreadRaw":0.00009} {"symbol":"EURUSD","ask":1.18725,"bid":1.18716,"high":1.18745,"low":1.18702,"askVolume":200000,"bidVolume":299000,"timestamp":1617750266993,"level":0,"quoteId":5,"spreadTable":0.9,"spreadRaw":0.00009} {"symbol":"EURUSD","ask":1.18725,"bid":1.18716,"high":1.18745,"low":1.18702,"askVolume":200000,"bidVolume":299000,"timestamp":1617750266993,"level":0,"quoteId":5,"spreadTable":0.9,"spreadRaw":0.00009} {"symbol":"EURUSD","ask":1.18726,"bid":1.18717,"high":1.18745,"low":1.18702,"askVolume":50000,"bidVolume":300000,"timestamp":1617750271371,"level":0,"quoteId":5,"spreadTable":0.9,"spreadRaw":0.00009} {"symbol":"EURUSD","ask":1.18726,"bid":1.18717,"high":1.18745,"low":1.18702,"askVolume":50000,"bidVolume":300000,"timestamp":1617750271371,"level":0,"quoteId":5,"spreadTable":0.9,"spreadRaw":0.00009} {"symbol":"EURUSD","ask":1.18726,"bid":1.18717,"high":1.18745,"low":1.18702,"askVolume":50000,"bidVolume":300000,"timestamp":1617750271371,"level":0,"quoteId":5,"spreadTable":0.9,"spreadRaw":0.00009} {"symbol":"EURUSD","ask":1.18726,"bid":1.18717,"high":1.18745,"low":1.18702,"askVolume":50000,"bidVolume":300000,"timestamp":1617750271371,"level":0,"quoteId":5,"spreadTable":0.9,"spreadRaw":0.00009} {"symbol":"EURUSD","ask":1.18726,"bid":1.18717,"high":1.18745,"low":1.18702,"askVolume":50000,"bidVolume":300000,"timestamp":1617750271371,"level":0,"quoteId":5,"spreadTable":0.9,"spreadRaw":0.00009} {"symbol":"EURUSD","ask":1.18726,"bid":1.18717,"high":1.18745,"low":1.18702,"askVolume":50000,"bidVolume":300000,"timestamp":1617750271371,"level":0,"quoteId":5,"spreadTable":0.9,"spreadRaw":0.00009} {"symbol":"EURUSD","ask":1.18726,"bid":1.18717,"high":1.18745,"low":1.18702,"askVolume":50000,"bidVolume":300000,"timestamp":1617750271371,"level":0,"quoteId":5,"spreadTable":0.9,"spreadRaw":0.00009} {"symbol":"EURUSD","ask":1.18726,"bid":1.18717,"high":1.18745,"low":1.18702,"askVolume":200000,"bidVolume":200000,"timestamp":1617750272636,"level":0,"quoteId":5,"spreadTable":0.9,"spreadRaw":0.00009} {"symbol":"EURUSD","ask":1.18726,"bid":1.18717,"high":1.18745,"low":1.18702,"askVolume":200000,"bidVolume":200000,"timestamp":1617750272636,"level":0,"quoteId":5,"spreadTable":0.9,"spreadRaw":0.00009} {"symbol":"EURUSD","ask":1.18726,"bid":1.18717,"high":1.18745,"low":1.18702,"askVolume":200000,"bidVolume":200000,"timestamp":1617750272636,"level":0,"quoteId":5,"spreadTable":0.9,"spreadRaw":0.00009} {"symbol":"EURUSD","ask":1.18726,"bid":1.18717,"high":1.18745,"low":1.18702,"askVolume":200000,"bidVolume":200000,"timestamp":1617750272636,"level":0,"quoteId":5,"spreadTable":0.9,"spreadRaw":0.00009} {"symbol":"EURUSD","ask":1.18726,"bid":1.18717,"high":1.18745,"low":1.18702,"askVolume":200000,"bidVolume":200000,"timestamp":1617750272636,"level":0,"quoteId":5,"spreadTable":0.9,"spreadRaw":0.00009} {"symbol":"EURUSD","ask":1.18726,"bid":1.18717,"high":1.18745,"low":1.18702,"askVolume":200000,"bidVolume":200000,"timestamp":1617750272636,"level":0,"quoteId":5,"spreadTable":0.9,"spreadRaw":0.00009} {"symbol":"EURUSD","ask":1.18726,"bid":1.18717,"high":1.18745,"low":1.18702,"askVolume":200000,"bidVolume":200000,"timestamp":1617750272636,"level":0,"quoteId":5,"spreadTable":0.9,"spreadRaw":0.00009}

onReject not called when host is unreachable

Hey, it's friday evening and xStation is closed due to maintenance, so the API is unreachable.

Just tried to get my balance via xapi-node but my Promise will never get resolved or rejected as connector.onReady or connector.onReject is never called.
I would expect connector.onReject should be called in this case or do you have any other callback for this case?

I think you should be able to reproduce this by setting options.host to any unknown host.

GetTickPrices stream hang up

Hi, I recently upgraded the library from the version 2.5.4 to the latest and I noticed that some times streaming socket for the tick prices might hang up, it will stop streaming and will not output any error.

This behavior will trigger at random intervals, I couldn't trace it back to any specific maintenance or market opening/closure, etc...

Once I downgraded back to the version 2.5.4 I was able to run it without interruption for a week.

This is my current code and you can safely assume the errors are handled at higher levels and there is a try-catch that will handle unhandled exceptions that might have slipped at any level.

try {
    EnvLogger.debug(`Preparing feed stream listener...`, DEFAULT_LOG_CONTEXT);
    SiemLogger.debug("", Object.assign({
      content: {
        description: `Preparing feed stream listener...`
      }
    }, DEFAULT_LOG_CONTEXT));

    xapiClient.Stream.listen.getTickPrices(async data => {
      SiemLogger.info("", Object.assign({
        content: {
          description: `Received: ${JSON.stringify(data)}`
        }
      }, DEFAULT_LOG_CONTEXT));

      let date = new Date(data.timestamp),
        year = date.getUTCFullYear(),
        month = date.getUTCMonth() + 1,
        day = date.getDate(),
        tmp = new Object({
          timestamp: date,
          year: year,
          month: month,
          day: day,
          ymj: Number(`${year}${month < 10 ? "0" + month : month}`),
          ymdj: Number(`${year}${month < 10 ? "0" + month : month}${day < 10 ? "0" + day : day}`),
          provider: "XTB",
          level: data.level,
          quote: data.quoteId,
          price: {
            ask: data.ask,
            mid: (data.ask + data.bid) / 2,
            bid: data.bid
          },
          volume: {
            ask: data.askVolume,
            bid: data.bidVolume
          },
          spread: {
            raw: data.spreadRaw,
            table: data.spreadTable
          }
        }),
        symbol = data.symbol.toUpperCase();

      if (Object.keys(insertProjection).length === 0 || (Object.keys(insertProjection).length > 0 && isContainedIn(insertProjection, tmp))) {
        EnvLogger.debug(`Datapoint ${JSON.stringify(tmp)} matched insert projection ${JSON.stringify(insertProjection)}`, DEFAULT_LOG_CONTEXT);
        SiemLogger.debug("", Object.assign({
          content: {
            description: `Datapoint ${JSON.stringify(tmp)} matched insert projection ${JSON.stringify(insertProjection)}`
          }
        }, DEFAULT_LOG_CONTEXT));

        mongodbUtils.insertOne(dbClient, dbName, symbol, tmp).then(err => {
	  date = null
          month = null
	  day = null
	  tmp = null
	  data = null
          if (err !== null) {
            EnvLogger.error(`Couldn't upload ${err.stack}`, DEFAULT_LOG_CONTEXT);
            SiemLogger.error("", Object.assign({
              content: {
                description: `Couldn't upload ${err.message}`
              }
            }, DEFAULT_LOG_CONTEXT));
          } else {
            EnvLogger.debug(`Uploded ${JSON.stringify(tmp)} to '${symbol}' successfully`, DEFAULT_LOG_CONTEXT);
            SiemLogger.debug("", Object.assign({
              content: {
                description: `Uploded ${JSON.stringify(tmp)} to '${symbol}' successfully`
              }
            }, DEFAULT_LOG_CONTEXT));
          }
        });
      }
    });


    EnvLogger.debug(`Subscribing to ${tickers.length} tickers...`, DEFAULT_LOG_CONTEXT);
    SiemLogger.debug("", Object.assign({
      content: {
        description: `Subscribing to ${tickers.length} tickers...`
      }
    }, DEFAULT_LOG_CONTEXT));

    for (let i = 0; i < tickers.length; i += 1) {
      xapiClient.Stream.subscribe.getTickPrices(tickers[i], 0);
      EnvLogger.info(`Subscribed to ${tickers[i]}`, DEFAULT_LOG_CONTEXT);
      SiemLogger.info("", Object.assign({
        content: {
          description: `Subscribed to ${tickers[i]}`
        }
      }, DEFAULT_LOG_CONTEXT));
    }

  } catch (err) {
    EnvLogger.error(`Unhandled exception: ${err.stack}`, DEFAULT_LOG_CONTEXT);
    SiemLogger.error("", Object.assign({
      status: "KO",
      elapsed: new Date().getTime() - startTime,
      content: {
        description: `Unhandled exception: ${err.message}`
      }
    }, DEFAULT_LOG_CONTEXT));
    resolve(null);
  }

streamSessionId available from login?

The XAPI documentation says:

After successful login the system responds with the status message that can contain the String representing streamSessionId field:

{
	"status": true,
	"streamSessionId": "8469308861804289383"
}

Are we able to get this information?

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.