veox / python3-krakenex

REST Exchange API for Kraken.com, Python 3
GNU Lesser General Public License v3.0
713 stars 236 forks source link

Adding 'close' order doesn't work: EAPI:Invalid key #124

Open Trogious opened 3 years ago

Trogious commented 3 years ago

Versions

OS: Mac, Linux
Python:  3.7.5
krakenex: 2.1.0

What are you trying to achieve?

Place buy 'limit' order with a closing 'stop-loss-profit' order.

# code sample
import json
import os

from krakenex import API

API_KEY = os.getenv('KRAKEN_API_KEY', '')
SECRET_KEY = os.getenv('KRAKEN_SECRET_KEY', '')

if __name__ == '__main__':
    api = API(API_KEY, SECRET_KEY)

    try_working = False

    if try_working:
        # this always works
        data = {'pair': 'XLTCZUSD', 'type': 'buy', 'ordertype': 'limit', 'price': '80.0', 'volume': '1.25'}
    else:
        # this always fails with: "EAPI:Invalid key"
        data = {'pair': 'XLTCZUSD', 'type': 'buy', 'ordertype': 'limit',
                'price': '80.0', 'volume': '1.25', 'close': {'ordertype': 'stop-loss-profit', 'price': '75.0', 'price2': '90.0'}}

    ret = api.query_private('AddOrder', data=data)
    print(json.dumps(ret, indent=2, sort_keys=True))

What do you expect to happen?

The order is placed as per my request.

What happens instead?

"EAPI:Invalid key" is returned when I try to place order with a close following one. It works for a simple order - i.e. without the closing one.

# error message
{
  "error": [
    "EAPI:Invalid key"
  ]
}
veox commented 3 years ago

Can confirm locally (Arch Linux, Python 3.8, krakenex 2.1.0) with syntax as in description; but see below.

veox commented 3 years ago

Note that this has not been the syntax the last it was tested:

    response = kraken.query_private('AddOrder',
                                    {'pair': 'XXBTZEUR',
                                     'type': 'buy',
                                     'ordertype': 'limit',
                                     'price': '1',
                                     'volume': '1',
                                     # `ordertype`, `price`, `price2` are valid
                                     'close[ordertype]': 'limit',
                                     'close[price]': '9001',
                                     # these will be ignored!
                                     'close[pair]': 'XXBTZEUR',
                                     'close[type]': 'sell',
                                     'close[volume]': '1'})

Can confirm the above still works; with (ipython):

In [39]: data = {'pair': 'XXBTZEUR', 
    ...:         'type': 'buy', 
    ...:         'ordertype': 'limit', 
    ...:         'price': '80.0', 
    ...:         'volume': '0.01', 
    ...:         'close[ordertype]': 'limit', 
    ...:         'close[price]': '90.0' 
    ...:         }

In [40]: kraken.query_private('AddOrder', data=data)       
Out[40]: 
{'error': [],
 'result': {'descr': {'order': 'buy 0.01000000 XBTEUR @ limit 80.0',
   'close': 'close position @ limit 90.0'},},
  'txid': ['POTATO-POTATO-POTATO']}}

Syntax as in issue report doesn't work:

In [41]: data = {'pair': 'XXBTZEUR', 
    ...:         'type': 'buy', 
    ...:         'ordertype': 'limit', 
    ...:         'price': '80.0', 
    ...:         'volume': '0.01', 
    ...:         'close': {'type': 'sell', 
    ...:                   'price': '90.0' 
    ...:                   }}

In [42]: kraken.query_private('AddOrder', data=data)       
Out[42]: {'error': ['EAPI:Invalid key']}
veox commented 3 years ago

The documentation at https://www.kraken.com/features/api#add-standard-order is likely misleading/outdated.

See discussion in issues #39 and #94 as possibly related.

veox commented 3 years ago

Also it looks like 'ordertype': 'stop-loss-profit' is available neither on Kraken's "New Order" page ATM, nor on trade.kraken.com - if it ever has been available. (Trailing stops certainly have been available previously, but were discontinued, that I do remember.)

Check the order interfaces for what is available to you. It's possible this is also dependent on trading tier.

veox commented 3 years ago

This syntax "works":

In [55]: data = {'pair': 'XXBTZEUR', 
    ...:         'type': 'buy', 
    ...:         'ordertype': 'limit', 
    ...:         'price': '80.0', 
    ...:         'volume': '0.01', 
    ...:         'close[type]': 'stop-loss-profit', 
    ...:         'close[price]': '70.0', 
    ...:         'close[price2]': '90.0' 
    ...:         }                                         

In [56]: kraken.query_private('AddOrder', data=data)       
Out[56]: 
{'error': [],
 'result': {'descr': {'order': 'buy 0.01000000 XBTEUR @ limit 80.0'},
  'txid': ['POTATO-POTATO-POTATO']}}

However, checking the order on Kraken (and also via the API OpenOrders query) shows that the order indeed does not have any closing data.

This is because type is determined automatically; what must be provided is a supported ordertype, e.g. limit. An unsupported ordertype will give an error, a missing ordertype will quietly drop the entire close[] order.

veox commented 3 years ago

Marking issue as upstream, due to their outdated/misleading docs; nothing to do on this end.


Still, note you're using improper syntax, too. This "works", showing that the provided ordertype is invalid:

In [77]: kraken.query_private('AddOrder', data={'pair': 'XXBTZEUR', 
    ...:         'type': 'buy', 
    ...:         'ordertype': 'limit', 
    ...:         'price': '90.0', 
    ...:         'volume': '0.01', 
    ...:         'close[ordertype]': 'stop-loss-profit', 
    ...:         'close[price]': '80.0', 
    ...:         'close[price2]': '100.0' 
    ...:         })                                        
Out[77]: {'error': ['EGeneral:Invalid arguments:/close-ordertype']}

As to the nature of the rather-misleading error...

{
  "error": [
    "EAPI:Invalid key"
  ]
}

This is probably because the nested data (dict-in-a-dict) is mangled beyond recognition during serialisation. The server then can't even decode the message.