async_v20 8.0.0b1
Asynchronous wrapper for OANDA's v20 REST API
License: MIT
Keywords: algorithmic trading oanda v20 REST asyncio

async_v20: Asynchronous OANDA v20 client
========================================
   *A foreign exchange client*

.. image:: https://raw.githubusercontent.com/jamespeterschinner/async_v20/master/doc/source/_static/async_v20-icon-128x128.png
   :height: 64px
   :width: 64px
   :alt: async-v20 logo

.. image:: https://travis-ci.org/jamespeterschinner/async_v20.svg?branch=master
   :target: https://travis-ci.org/jamespeterschinner/async_v20
   :align: right

.. image:: https://codecov.io/gh/jamespeterschinner/async_v20/branch/master/graph/badge.svg
   :target: https://codecov.io/gh/jamespeterschinner/async_v20

.. image:: https://readthedocs.org/projects/async-v20/badge/?version=latest
   :target: http://async-v20.readthedocs.io/en/latest/?badge=latest
   :alt: Documentation Status


Documentation
-------------

http://async-v20.readthedocs.io/

Disclaimer
----------

- Losses can exceed investment.
- async_v20 and its creator has no affiliation with OANDA. And is not endorsed by OANDA in any manner.
- async_v20 is in Beta stage and has not been tested on a live OANDA account
- **Use at own risk**

Features
---------

- Exposes the entire v20 API
- No `*args, **kwargs` In client methods. Therefore no need to guess what arguments a method takes
- Serialize objects directly into *pandas* **Series** or **DataFrame** objects
- Construct *concurrent* trading algorithms



installation
------------

**REQUIRES:**

python >= 3.6

https://www.python.org/

    $ pip install async_v20


`async_v20` is built with `aiohttp <https://github.com/aio-libs/aiohttp>`_.
It is therefore recommended to also install `cchardet` and `aiodns` as per `aiohttp`
`documentation <http://aiohttp.readthedocs.io/en/stable/>`_

.. code-block:: bash

   $ pip install cchardet

   $ pip install aiodns

Why async_v20?
--------------

There are many OANDA clients for python already available so why create another?
The main driver for creating async_v20 was to facilitate better risk management,
by allowing user's to concurrently monitor account status and trade currency's.

An unintended consequence of async_v20 is the ability to create clear segregation
between implementation ideas.

A simple example might contain a coroutine for the following:

    - Monitoring overall account status
    - Watching price stream and triggering buy/sell signals
    - Monitoring individual trades and closing movements against held positions

A synchronous implementation would require considerable effort to determine which
task communicates with the server next. async_v20 removes this burden by using
`aiohttp <https://github.com/aio-libs/aiohttp>`_

Further goals of async_v20 has been to lower the barrier of entry for algorithmic trading
by providing a complete and simple to use interface.


Getting started
===============


Creating an Account
-------------------

To use `async_v20` you must have an account with *OANDA*

- Create an account

    https://www.oanda.com/account/login
- Create an API *token*

    https://www.oanda.com/demo-account/tpa/personal_token

Setting up environment
----------------------

- Install `async_v20` as per **installation**
- Create a new *environment variable* with the name 'OANDA_TOKEN' and value as the *token* generated from above


**Note:**

- It is considered best practice use a *virtual environment*
- It is not required to store the token in an *environment variable*. The token can be passed to OandaClient

Using async_v20
---------------

Once an account has been created as per *create-account*
and the environment is configured as per *setting-up-environment*
we are ready to begin.

Lets first take a look at this code example, then go though it line by line.


.. code-block:: python

   import asyncio

   from async_v20 import OandaClient


   async def get_account():
       async with OandaClient() as client:
           return await client.account()


   loop = asyncio.get_event_loop()
   account = loop.run_until_complete(get_account())

   # pandas Series
   print(account.series())

   # HTTP response state
   print(account)

   # JSON data in python dictionary format
   print(account.dict())


First we need to import *asyncio* this allows us to run our *coroutine*

.. code-block:: python

    import asyncio


We then import *OandaClient* which provides us the means to interact with OANDA

.. code-block:: python

    from async_v20 import OandaClient


Because *OandaClient* returns *coroutines* we use *async def*. This allows the use of the *await* syntax

.. code-block:: python

    async def get_account():


*OandaClient* is a *context manager*, we use *async with* to instantiate a
client instance. Doing so will automatically close the *http session* when we're done

.. code-block:: python

        async with OandaClient() as client:


We then create and *run* the *coroutine* by calling *client*. **account()**

.. code-block:: python

            return await client.account()


Now we have defined our *coroutine* we need to execute it.
To do so we need an event loop. Achieved using *asyncio*. **get_event_loop()**

.. code-block:: python

    loop = asyncio.get_event_loop()


The value returned by executing the `account()` *coroutine* is accessed through the event loop.

.. code-block:: python

    account = loop.run_until_complete(get_account())


`async_v20` objects have a **series()** method that returns a `pandas`. **Series**.
By default `async_v20`. **DateTime**'s will be converted into `pandas`. **Timestamp**'s.

.. code-block:: python

    print(account.series())


**Outputs**

.. code-block:: python

   alias                                                          Primary
   balance                                                        97801.9
   commission                                                           0
   created_by_user_id                                             1234567
   created_time                       2017-08-11 15:04:31.639182352+00:00
   currency                                                           AUD
   financing                                                      -3.5596
   hedging_enabled                                                  False
   id                                                 123-123-1234567-123
   last_margin_call_extension_time                                   None
   last_transaction_id                                               6360
   margin_available                                               97801.9
   margin_call_enter_time                                            None
   margin_call_extension_count                                       None
   margin_call_margin_used                                              0
   margin_call_percent                                                  0
   margin_closeout_margin_used                                          0
   margin_closeout_nav                                            97801.9
   margin_closeout_percent                                              0
   margin_closeout_position_value                                       0
   margin_closeout_unrealized_pl                                        0
   margin_rate                                                       0.02
   margin_used                                                          0
   nav                                                            97801.9
   open_position_count                                                  0
   open_trade_count                                                     0
   orders                                                              []
   pending_order_count                                                  0
   pl                                                            -2194.53
   position_value                                                       0
   positions                                                           []
   resettable_pl                                                 -2194.53
   resettabled_pl_time                                               None
   trades                                                              []
   unrealized_pl                                                        0
   withdrawal_limit                                               97801.9
   dtype: object

Changelog
=========

8.0.0b0 (01/01/2019)
====================

- Added guaranteedStopLossOrderRestriction to Instrument definition
- Added unixTime attribute to orderBook definition
- Added tags attribute to Instrument definition
- Added guaranteed to StopLossOrder definition
- Replaced ellipsis (...) with sentinel object
- Added fullVWAP to Transaction definition
- UnknownValue Exception is now replaced with UnknownKeywordArgument Warning
  in order to make the client more robust to breaking changes from OANDA
- Checked many class definitions against updated OANDA documentation

7.0.1b0
=======
- OandaClient.close is now a coroutine

7.0.0b0
=======

- All OrderRequests now require an `instrument` as there first parameter.
  This is to allow correct rounding of decimal numbers to the instruments specification.
- `guaranteed: bool` has been added to Transaction definition.
- Default SinceTransactionID value is now limited to the passed 900 transactions.
- `OandaClient.account()` method will use `get_account_details()` method when default
  `SinceTransactionID` has expired.
- `OandaClient.get_pricing` now accepts an `InstrumentName` for `instruments`


6.2.2b0
=======

- `guaranteed: bool` has been added to Order definition.

6.2.1b0
=======

- Array class lazy instantiates objects
- Model objects with same attributes now compare equal (proving equal DateTime format)
- Improved repr of Array objects
- Improved implementation of `get_instrument`/s, `get_id`
- All Array objects have `get_instrument` and `get_instruments`. Returns either the first or all matching objects
- Removed Model class `_template` attribute as it was obsolete
- Added `get(self, name, default=None)` method to Model to allow for dict like key access.

6.2.0b0
=======

- Changed `get_transactions` method to `get_transaction` (API call can only return one transaction)
- Removed default parameter argument for `get_transaction`.(**transaction_id**) it is a required parameter.
- Made OandaClient.hosts a protected member. Now OandaClient._hosts
- `Array`. **get_instruments()** returns an Array of the same type this is when there is a one to many relationship
  between the instrument and objects the array contains. `Array`. **get_instrument()** Returns the single object
  when there is a one to one relationship. Both methods are mutually exclusive
- All objects now lazy instantiate attribute instances.
- Large refactoring of async_v20.definitions.base

6.1.0b0
=======

- Changed incorrect naming _i_ds to _ids
- Fixed OrderRequest formatting when a OrderRequest instance is passed that defines an instrument.

6.0.2b0
=======

- Fixed InvalidFormatRequest Error when OrderRequest does not define an `instrument` attribute

6.0.1b0
=======

- Fixed incorrect handling of stream response when endpoint returned status 400

6.0.0b0
=======

- Added health API and initialization check
- Fixed stream_transactions. Now returns correct type
- Changed streaming responses keys. Where stream_pricing() returned 'PRICE' or 'HEARTBEAT'
  response now contains 'price' or 'heartbeat'. Like wise stream_transactions() now returns
  'transaction' or 'heartbeat'. This has been done to standardise access to the transaction
  stream response and 'heartbeat' objects. Due to the different types these objects may take.
- Added async_v20.exceptions module
- Added logging to modules

5.0.3b0
=======

- Added default argument to Array.get_id & Array.get_instrument
- Removed default value from get_candles(*count*)

5.0.2b0
=======

- Fixed bug in rest implementation. Positions now update correctly

5.0.1b0
=======

- OandaClient.datetime_format is read only
- OandaClient._instruments is no longer a protected attribute. It is now OandaClient.instruments

5.0.0b0
=======

- DateTime's create pandas.Timestamp's
- Model.dict argument `datetime` is now `datetime_format`. Argument behaviour now
  specifies the representation of times. Either `RFC3339` or `UNIX`. Corresponding `json` argument
  changes the representation of UNIX times to either a `str` or `numpy.int64`
- *Response* .json() accepts `datetime_format` argument string

4.0.0b0
=======

- Changed get_positions to get_position (as method can only close one position)
- _in_context accepts negative units


3.0.0b0
=======

- Array.get_instrument() works with ArrayInstrument
- OandaClient.initialize() gets account instruments
- OandaClient has `format_order_request` attribute
- async_v20.definitions.primitives.Unit has been removed
- PriceValue and Decimal number has additional method `format(precision, min_, max_)`

2.3.0b0
=======

- Updated limit_replace_order() method to expose all arguments
- TransactionID, TradeID & OrderID get stored as integers and cast to strings when creating JSON
  representations
- Added documentation for order API methods


2.2.5b2
=======

- Fixed get_candles default value

2.2.5b1
=======

- RejectTransactions have no required arguments
- API methods now apply default values
- Added undocumented attributes
- Path class has been removed in favour of helper function. Allowing for more useful
  error message on failure.

2.2.5b0
=======

- PriceComponent accepts all combinations of 'M' 'A' 'B'

2.2.4b3
=======

Added attributes to TradeSummary:
    - margin_used


2.2.4b1
=======

Added attributes to TradeReduce:
    - guaranteed_execution_fee

2.2.4b0
=======

Added attributes to Transaction:
    - guaranteed_execution_fee
    - gain_quote_home_conversion_factor
    - loss_quote_home_conversion_factor

Added attributes to TradeOpen:
    - price
    - guaranteed_execution_fee


2.2.3b0
=======

- Added 'margin_used' to Position object.
  (OANDA added new attribute, causing error)
- Added TimeoutError to stream


2.2.2b0
=======

- Added get_position_book and get_order_book API calls

2.2.1b0
=======

- series() method converts both UNIX and RFC3339 time's to pandas.Timestamp 's


2.2.0b0
=======

- Initialization doesn't freeze after failure
- Order methods exposes all arguments

2.1.0b0
=======

- Beta release. At present time client is considered feature full
  with 100% test coverage
- _fields attribute stored on instance not class
- RESTful account() method added
- close_all_trades() method added
- Added replace() method to Model
- Simplified Endpoint decorator (No serial requests)
- Changes close_trades to close_trade (Method can only close one trade)
- Response parser checks HTTP status first
- Added tests

2.0.1a0
=======

- `type` argument is set automatically for subclass that define it
- implementation improvements

2.0.0a0
=======

- async_v20 objects are now immutable (greatly reducing complexity)
- Objects now have a repr
- removed inflection as a dependency
- Higher test coverage

1.1.6a0
=======

- Issue with object serialization not working with lists of Type[str, float, int]

1.1.5a4
=======

- Argument passing

1.1.5a3
=======

- Fix long description on PyPI


1.1.5a0
=======

- method signatures were offset buy 1 argument due to handling of
  'self' parameter. Methods now displaying correct signature


1.1.4a0
=======

- Fixed incorrect annotation on:
- PUTPositionsInstrumentClose
- GETPositionsInstrument


1.1.3a0
=======

- Fixed incorrect annotation on Interface methods
- Fixed argument passing bug caused by false'y evaluation


1.1.2a5
=======

- Added Travis CI
- Added Codecov


1.1.2a4
=======

- Additional documentation

1.1.2a1
=======

- OandaClient.initialize() method is now exposed
- OandaClient is now also a context manager. To automatically close the http session
- Additional documentation


1.1.1a1
=======

- Floating point numbers are rounded to the correct accuracy required for correct
  serialization.

1.1.0a1
=======


- Model.series() returns data in more specific types instead of all 'str'
- OandaClient methods now have correct signature instead of args, kwargs


1.0.1a1
=======

- Fixed code examples in bin directory