[
  {
    "path": ".gitignore",
    "content": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n\n# C extensions\n*.so\n\n# Distribution / packaging\n.Python\nenv/\nbuild/\ndevelop-eggs/\ndist/\ndownloads/\neggs/\nlib/\nlib64/\nparts/\nsdist/\nvar/\n*.egg-info/\n.installed.cfg\n*.egg\n\n# PyInstaller\n#  Usually these files are written by a python script from a template\n#  before PyInstaller builds the exe, so as to inject date/other infos into it.\n*.manifest\n*.spec\n\n# Installer logs\npip-log.txt\npip-delete-this-directory.txt\n\n# Unit test / coverage reports\nhtmlcov/\n.tox/\n.coverage\n.cache\nnosetests.xml\ncoverage.xml\n\n# Translations\n*.mo\n*.pot\n\n# Django stuff:\n*.log\n\n# Sphinx documentation\ndocs/_build/\n\n# PyBuilder\ntarget/\n"
  },
  {
    "path": ".landscape.yml",
    "content": "inherits: [flake8]\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: python\npython:\n- '3.6'\n- '3.7'\n- '3.8'\n- '3.9'\ninstall:\n- pip install --upgrade pip setuptools\n- pip install requests-mock\n- pip install coveralls\n- pip install nose nose-parameterized\n- pip install wheel\n- pip install twine\nscript:\n- coverage run --source=oandapyV20 setup.py test\nafter_success:\n- coveralls\ndeploy:\n  provider: pypi\n  user: hootnot\n  password:\n    secure: Jr+/eYSrysSQcSaC8gW5TJak3AycoMlPe3QfOE/CV7n9RYn5JsXudUhWTFiC4c78CAGu14F3Iu6TQPiC0CZrWc04Gi9H1xnWniAXRsr8xKiSfyL1zpHRoBmP6zbdOGc6zk8Jjit1YUNSdp2W/YA7Ii1BwwLQ/h+er8IqZxoGNs3kh51G/2dYOU085VELbz9S1um27e+oJuAOurrfZiPGdjnnUVALfQcuRrEWRS3Cc+1LDiKbHWD1dBlVvf71okyBAd2gnT+bBjCpKiBmjHzEnRO2mdjPBA+2lOI8EOr0E3Ueb/9q3ID3H9UPnb2ZL9VhqxutLVB0fEbHpiAPcG7MPwKN8EWTDIPDGUP9/DEUDX0qV0eybP8yl/5+2l4np0a+cqSkHJfeLZwxixaOs02qP6SMScxfsf+N6BhlIKCpNnESkpsdESlkgG0lxkoJVOR8Pf0otTd0lIjLl/Iy4I7SoRwFNHiUg1naQHIVvbFdsYeM0KZQUQtLEUN/pcjZkRJsHkZHZNo/KSB27xECbPUcrzBorMc8EL1s9H51q8HhhDufnAel3Y0IW3aMR4cN3gX0H+udEEbWgeVf7p7xZESJgmntYoHWICpzK2uNvxJZ2+gkJQKPL4fERSskjo+7UUf6mwi32HNk0oAOyGDGxtgbCEyZ0GazZLzFYAIsiR1Uj88=\n  on:\n    tags: true\n    distributions: sdist bdist_wheel\n    repo: hootnot/oanda-api-v20\n"
  },
  {
    "path": "CHANGELOG.rst",
    "content": "Changelog\n=========\n\n[Unreleased]\n------------\n\nv0.7.2 (2021-08-26)\n-------------------\n\nDocumentation Changes\n~~~~~~~~~~~~~~~~~~~~~\n\n-  [endpoints] fix -> trades.TradeDetails\n\nv0.7.1 (2021-08-15)\n-------------------\n\nBug Fixes\n~~~~~~~~~\n\n-  [types] make Units handle up to 2 decimals (was 1)\n\nv0.7.0 (2021-05-25)\n-------------------\n\nBug Fixes\n~~~~~~~~~\n\n-  [test] test_orders: fix fail python 3.9\n\n-  [types] make Units handle up to 1 decimal\n\nDocumentation Changes\n~~~~~~~~~~~~~~~~~~~~~\n\n-  using the with context\n\nAdministration and Chores\n~~~~~~~~~~~~~~~~~~~~~~~~~\n\n-  rename CHANGES.txt -> CHANGELOG.rst\n\n-  [versions] support Python 3.5 - 3.9\n\nVersion 0.6.3\n-------------\n\n2018/04/12\n          update of definitions according v20-openapi release 3.0.22\n\nVersion 0.6.2\n-------------\n\n2018/04/07\n          granularity_to_time now also handles weekly 'W' as parameter,\n          see PR #119. Tests added.\n\nVersion 0.6.1\n-------------\n\n2018/03/31\n          InstrumentsCandlesFactory fix, incorrect handling of parameters\n          in the rare case one would not specify the 'from' parameter,\n          see PR #117\n\nVersion 0.6.0\n-------------\n\n2018/03/07\n          support added for the (legacy) forexlabs endpoints, #110. See\n          developer.oanda.com for details.\n\nVersion 0.5.0\n-------------\n\n2018/02/18\n          update various definitions as OANDA added these to their docs\n\nVersion 0.4.5\n-------------\n\n2017/09/25\n          force 'includeFirst' in InstrumentsCandlesFactory, #100\n\nVersion 0.4.4\n-------------\n\n2017/09/23\n          fix bug in InstrumentsCandlesFactory skipping the last request, #97\n\nVersion 0.4.3\n-------------\n\n2017/08/21\n          fix missing gtdTime in LimitOrderRequest, #94\n\nVersion 0.4.2\n-------------\n\n2017/07/24\n          fix possible 'date is in the future' error when retrieving candledata\n          using InstrumentsCandlesFactory\n\nVersion 0.4.1\n-------------\n\n2017/07/11:\n          bugfix, see pr #85\n\nVersion 0.4.0\n-------------\n\n2017/07/04:\n          contrib.factories added, pr #81:\n          InstrumentsCandlesFactory to generate InstrumentsCandles requests\n\nVersion 0.3.0\n-------------\n\n2017/06/28:\n          Recently released extra instruments endpoints added, pr #77:\n          /v3/instruments/{instrument}/orderBook\n          /v3/instruments/{instrument}/positionBook\n\nVersion 0.2.4\n-------------\n2017/05/15:\n          documentation fix regarding incorrect output references of\n          AccountList and AccountDetails, #pr 73\n\nVersion 0.2.3\n-------------\n2017/04/17:\n          fix: trades.TradesList unhandled params, issue #69\n\n2017/03/09:\n          jupyter notebooks added\n\n2017/02/08:\n          Python 3.6 added\n\n2017/01/30:\n          datetime name conflict solved, issue #62\n\n2016/12/05:\n          documentation: dynamically generated types directory tree\n\n          types: DateTime subsecond part fix\n\n2016/12/05:\n          fixes OrderSpecifier\n\n2016/12/01:\n          extend types with DateTime\n\n2016/11/17:\n          bug streaming prices: list values need to be joined, solved #50\n\nVersion 0.2.2\n-------------\n2016/11/17:\n          extend types with AccountID\n          definitions\n          increase coverage\n          contrib.request classes timeInForce parameter add and/or verify\n          against allowed values\n\nVersion 0.2.1\n-------------\n2016/11/15:\n          * documentation updates\n          * missing requirement: six added\n\nVersion 0.2.0\n-------------\n2016/11/15:\n\n          * first release with coverage of all endpoints except the 'forexlabs'\n          * definitions covered as in the development documeintation\n          * types representing data types as in the development documeintation\n          * contrib.requests: classes to construct data for requestbodies\n"
  },
  {
    "path": "LICENSE.md",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2016 Feite Brekeveld\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 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.\n"
  },
  {
    "path": "MANIFEST.in",
    "content": "include requirements.txt\ninclude LICENSE.md\n"
  },
  {
    "path": "README.rst",
    "content": "OANDA REST-V20 API wrapper\n==========================\n\n.. _Top:\n\nAs of march 2018 OANDA no longer supports the v1 REST-API. The only pending\nV20 endpoint was the *forexlabs endpoint*. Instead of launching *forexlabs*\nas a *V20-endpoint*, OANDA choose to support this endpoint from the v1\nREST interface, see: http://developer.oanda.com/rest-live-v20/forexlabs-ep/.\n\n\n.. image:: https://travis-ci.org/hootnot/oanda-api-v20.svg?branch=master\n   :target: https://travis-ci.org/hootnot/oanda-api-v20\n   :alt: Build\n\n.. image:: https://readthedocs.org/projects/oanda-api-v20/badge/?version=latest\n   :target: http://oanda-api-v20.readthedocs.io/en/latest/?badge=latest\n   :alt: Documentation Status\n\n.. image:: https://landscape.io/github/hootnot/oanda-api-v20/master/landscape.svg?style=flat\n   :target: https://landscape.io/github/hootnot/oanda-api-v20/master\n   :alt: Code Health\n\n.. image:: https://coveralls.io/repos/github/hootnot/oanda-api-v20/badge.svg?branch=master\n   :target: https://coveralls.io/github/hootnot/oanda-api-v20?branch=master\n   :alt: Coverage\n\n.. image:: https://badge.fury.io/py/oandapyV20.svg\n   :target: https://badge.fury.io/py/oandapyV20\n   :alt: Pypi\n\n.. image:: https://img.shields.io/pypi/pyversions/oandapyV20.svg\n   :target: https://pypi.org/project/oandapyV20\n   :alt: Python versions\n\n.. image:: https://api.codacy.com/project/badge/Grade/5946514e3a7c407291f76e630ce3553b \n   :target: https://www.codacy.com/app/hootnot/oandaapiv20utm_source=github.com&amp;utm_medium=referral&amp;utm_content=hootnot/oanda-api-v20&amp;utm_campaign=Badge_Grade\n   :alt: Codacy\n\n\nInteractive\n-----------\n\n.. image:: https://jupyter.readthedocs.io/en/latest/_static/_images/jupyter.svg\n   :target: ./jupyter\n   :alt: Jupyter\n\nUsing the Jupyter `notebook`_ it is easy to play with the\n*oandapyV20* library.\n\n.. _notebook: ./jupyter/index.ipynb\n\nTOC\n---\n\n   + `Install`_\n   + `Design`_\n   + `Client`_\n       - `contrib.requests`_\n       - `contrib.factories`_\n       - `API-endpoint access`_\n       - `Placing a MarketOrder with TakeProfitOrder and StopLossOrder`_\n       - `Processing series of requests`_\n       - `Streaming endpoints`_\n\nInstall\n-------\n\n.. code-block:: bash\n\n    $ pip install oandapyV20\n\n\nor the latest development version from github:\n\n.. code-block:: bash\n\n    $ pip install git+https://github.com/hootnot/oanda-api-v20.git\n\nIf you want to run the tests, clone the repository:\n\n.. code-block:: bash\n\n    $ git clone https://github.com/hootnot/oanda-api-v20\n    $ cd oanda-api-v20\n\n    # install necessary packages for testing\n    $ grep \"\\- pip install\" .travis.yml |\n    > while read LNE\n    > do `echo $LNE| cut -c2-` ; done\n\n    $ python setup.py test\n    $ python setup.py install\n\nExamples are provided in the https://github.com/hootnot/oandapyV20-examples\nrepository.\n\n\n\nDesign\n------\n\nIn the V20-library endpoints are represented as APIRequest objects derived from the\nAPIRequest base class. Each endpoint group (accounts, trades, etc.) is represented\nby it's own (abstract) class covering the functionality of all endpoints for that group. Each endpoint within that group is covered by a class derived from\nthe abstract class.\n\nTop_\n\nClient\n~~~~~~\n\nThe V20-library has a client class (API) which processes APIRequest objects.\n\nTop_\n\ncontrib.requests\n~~~~~~~~~~~~~~~~\n\nThe contrib.request package offers classes providing an easy way\nto construct the data for the *data* parameter of the OrderCreate endpoint\nor the TradeCRCDO (Create/Replace/Cancel Dependent Orders).\n\n.. code-block:: python\n\n    mktOrder = MarketOrderRequest(instrument=\"EUR_USD\",\n         units=10000,\n         takeProfitOnFill=TakeProfitDetails(price=1.10).data,\n         stopLossOnFill=StopLossDetails(price=1.07).data\n    ).data\n\n\n    instead of:\n\n.. code-block:: python\n\n    mktOrder = {'order': {\n                   'timeInForce': 'FOK',\n                   'instrument': 'EUR_USD',\n                   'positionFill': 'DEFAULT',\n                   'units': '10000',\n                   'type': 'MARKET',\n                   'takeProfitOnFill': {\n                       'timeInForce': 'GTC',\n                       'price': '1.10000'}\n                   }\n                   'stopLossOnFill': {\n                       'timeInForce': 'GTC',\n                       'price': '1.07000'}\n                   }\n               }\n\n\nTop_\n\ncontrib.factories\n~~~~~~~~~~~~~~~~~\n\nThe contrib.factories module offers classes providing an easy way\ngenerate requests.\nDownloading historical data is limited to 5000 records per request. This\nmeans that you have to make consecutive requests with change of parameters\nif you want more than 5000 records.\n\nThe *InstrumentsCandlesFactory* solves this by generating the requests for you,\nexample:\n\n.. code-block:: python\n\n   import sys\n   import json\n\n   from oandapyV20.contrib.factories import InstrumentsCandlesFactory\n   from oandapyV20 import API\n\n   access_token = \"...\"\n\n   client = API(access_token=access_token)\n\n   _from = sys.argv[1]\n   _to = sys.argv[2]\n   gran = sys.argv[3]\n   instr = sys.argv[4]\n\n   params = {\n       \"granularity\": gran,\n       \"from\": _from,\n       \"to\": _to\n   }\n\n   def cnv(r, h):\n       for candle in r.get('candles'):\n           ctime = candle.get('time')[0:19]\n           try:\n               rec = \"{time},{complete},{o},{h},{l},{c},{v}\".format(\n                   time=ctime,\n                   complete=candle['complete'],\n                   o=candle['mid']['o'],\n                   h=candle['mid']['h'],\n                   l=candle['mid']['l'],\n                   c=candle['mid']['c'],\n                   v=candle['volume'],\n               )\n           except Exception as e:\n               print(e, r)\n           else:\n               h.write(rec+\"\\n\")\n\n   with open(\"/tmp/{}.{}.out\".format(instr, gran), \"w\") as O:\n       for r in InstrumentsCandlesFactory(instrument=instr, params=params):\n           print(\"REQUEST: {} {} {}\".format(r, r.__class__.__name__, r.params))\n           rv = client.request(r)\n           cnv(r.response, O)\n\n\nWhen running this:\n\n.. code-block:: shell\n\n   $ python oandahist.py 2017-01-01T00:00:00Z 2017-06-30T00:00:00Z H4 EUR_USD\n   REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles\n   {'to': '2017-03-25T08:00:00Z',\n    'from': '2017-01-01T00:00:00Z', 'granularity': 'H4'}\n   REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles\n   {'to': '2017-06-16T20:00:00Z', 'from': '2017-03-25T12:00:00Z',\n    'granularity': 'H4'}\n   REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles\n   {'to': '2017-06-30T00:00:00Z', 'from': '2017-06-17T00:00:00Z',\n    'granularity': 'H4'}\n\n\nThe output shows it processed three *InstrumentsCandles* requests. The\ndata can be found in */tmp/EUR_USD.H4.out*:\n\n.. code-block:: shell\n\n   $ tail /tmp/EUR_USD.H4.out\n   ...\n   2017-06-28T01:00:0,True,1.13397,1.13557,1.13372,1.13468,1534\n   2017-06-28T05:00:0,True,1.13465,1.13882,1.13454,1.13603,8486\n   2017-06-28T09:00:0,True,1.13606,1.13802,1.12918,1.13315,12815\n   2017-06-28T13:00:0,True,1.13317,1.13909,1.13283,1.13781,13255\n   2017-06-28T17:00:0,True,1.13783,1.13852,1.13736,1.13771,2104\n   2017-06-28T21:00:0,True,1.13789,1.13894,1.13747,1.13874,1454\n\n\nTop_\n\nExamples\n--------\n\nAPI-endpoint access\n~~~~~~~~~~~~~~~~~~~\n\n.. code-block:: python\n\n    import json\n    from oandapyV20 import API    # the client\n    import oandapyV20.endpoints.trades as trades\n\n    access_token = \"...\"\n    accountID = \"...\"\n    client = API(access_token=access_token)\n\n    # request trades list\n    r = trades.TradesList(accountID)\n    rv = client.request(r)\n    print(\"RESPONSE:\\n{}\".format(json.dumps(rv, indent=2)))\n\n\nTop_\n\nPlacing a *MarketOrder* with *TakeProfitOrder* and *StopLossOrder*\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n.. code-block:: python\n\n    import json\n\n    from oandapyV20.contrib.requests import MarketOrderRequest\n    from oandapyV20.contrib.requests import TakeProfitDetails, StopLossDetails\n\n    import oandapyV20.endpoints.orders as orders\n    import oandapyV20\n\n    from exampleauth import exampleAuth\n\n\n    accountID, access_token = exampleAuth()\n    api = oandapyV20.API(access_token=access_token)\n\n    # EUR_USD (today 1.0750)\n    EUR_USD_STOP_LOSS = 1.07\n    EUR_USD_TAKE_PROFIT = 1.10\n\n    mktOrder = MarketOrderRequest(\n        instrument=\"EUR_USD\",\n        units=10000,\n        takeProfitOnFill=TakeProfitDetails(price=EUR_USD_TAKE_PROFIT).data,\n        stopLossOnFill=StopLossDetails(price=EUR_USD_STOP_LOSS).data)\n\n    # create the OrderCreate request\n    r = orders.OrderCreate(accountID, data=mktOrder.data)\n    try:\n        # create the OrderCreate request\n        rv = api.request(r)\n    except oandapyV20.exceptions.V20Error as err:\n        print(r.status_code, err)\n    else:\n        print(json.dumps(rv, indent=2))\n\n\nTop_\n\nProcessing series of requests\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nProcessing series of requests is also possible now by storing different requests in\nan array or from some 'request-factory' class. Below an array example:\n\n.. code-block:: python\n\n     import json\n     from oandapyV20 import API    # the client\n     from oandapyV20.exceptions import V20Error\n     import oandapyV20.endpoints.accounts as accounts\n     import oandapyV20.endpoints.trades as trades\n     import oandapyV20.endpoints.pricing as pricing\n\n     access_token = \"...\"\n     accountID = \"...\"\n     client = API(access_token=access_token)\n\n     # list of requests\n     lor = []\n     # request trades list\n     lor.append(trades.TradesList(accountID))\n     # request accounts list\n     lor.append(accounts.AccountList())\n     # request pricing info\n     params={\"instruments\": \"DE30_EUR,EUR_GBP\"}\n     lor.append(pricing.PricingInfo(accountID, params=params))\n\n     for r in lor:\n         try:\n             rv = client.request(r)\n             # put request and response in 1 JSON structure\n             print(\"{}\".format(json.dumps({\"request\": \"{}\".format(r),\n                                           \"response\": rv}, indent=2)))\n         except V20Error as e:\n             print(\"OOPS: {:d} {:s}\".format(e.code, e.msg))\n\nOutput\n``````\n\n.. code-block:: json\n\n    {\n      \"request\": \"v3/accounts/101-004-1435156-001/trades\",\n      \"response\": {\n        \"lastTransactionID\": \"1109\",\n        \"trades\": [\n          {\n            \"unrealizedPL\": \"23.0000\",\n            \"financing\": \"-0.5556\",\n            \"state\": \"OPEN\",\n            \"price\": \"10159.4\",\n            \"realizedPL\": \"0.0000\",\n            \"currentUnits\": \"-10\",\n            \"openTime\": \"2016-07-22T16:47:04.315211198Z\",\n            \"initialUnits\": \"-10\",\n            \"instrument\": \"DE30_EUR\",\n            \"id\": \"1105\"\n          },\n          {\n            \"unrealizedPL\": \"23.0000\",\n            \"financing\": \"-0.5556\",\n            \"state\": \"OPEN\",\n            \"price\": \"10159.4\",\n            \"realizedPL\": \"0.0000\",\n            \"currentUnits\": \"-10\",\n            \"openTime\": \"2016-07-22T16:47:04.141436468Z\",\n            \"initialUnits\": \"-10\",\n            \"instrument\": \"DE30_EUR\",\n            \"id\": \"1103\"\n          }\n        ]\n      }\n    }\n\n    {\n      \"request\": \"v3/accounts\",\n      \"response\": {\n        \"accounts\": [\n          {\n            \"tags\": [],\n            \"id\": \"101-004-1435156-002\"\n          },\n          {\n            \"tags\": [],\n            \"id\": \"101-004-1435156-001\"\n          }\n        ]\n      }\n    }\n\n    {\n      \"request\": \"v3/accounts/101-004-1435156-001/pricing\",\n      \"response\": {\n        \"prices\": [\n          {\n            \"status\": \"tradeable\",\n            \"quoteHomeConversionFactors\": {\n              \"negativeUnits\": \"1.00000000\",\n              \"positiveUnits\": \"1.00000000\"\n            },\n            \"asks\": [\n              {\n                \"price\": \"10295.1\",\n                \"liquidity\": 25\n              },\n              {\n                \"price\": \"10295.3\",\n                \"liquidity\": 75\n              },\n              {\n                \"price\": \"10295.5\",\n                \"liquidity\": 150\n              }\n            ],\n            \"unitsAvailable\": {\n              \"default\": {\n                \"short\": \"60\",\n                \"long\": \"100\"\n              },\n              \"reduceOnly\": {\n                \"short\": \"0\",\n                \"long\": \"20\"\n              },\n              \"openOnly\": {\n                \"short\": \"60\",\n                \"long\": \"0\"\n              },\n              \"reduceFirst\": {\n                \"short\": \"60\",\n                \"long\": \"100\"\n              }\n            },\n            \"closeoutBid\": \"10293.5\",\n            \"bids\": [\n              {\n                \"price\": \"10293.9\",\n                \"liquidity\": 25\n              },\n              {\n                \"price\": \"10293.7\",\n                \"liquidity\": 75\n              },\n              {\n                \"price\": \"10293.5\",\n                \"liquidity\": 150\n              }\n            ],\n            \"instrument\": \"DE30_EUR\",\n            \"time\": \"2016-09-29T17:07:19.598030528Z\",\n            \"closeoutAsk\": \"10295.5\"\n          },\n          {\n            \"status\": \"tradeable\",\n            \"quoteHomeConversionFactors\": {\n              \"negativeUnits\": \"1.15679152\",\n              \"positiveUnits\": \"1.15659083\"\n            },\n            \"asks\": [\n              {\n                \"price\": \"0.86461\",\n                \"liquidity\": 1000000\n              },\n              {\n                \"price\": \"0.86462\",\n                \"liquidity\": 2000000\n              },\n              {\n                \"price\": \"0.86463\",\n                \"liquidity\": 5000000\n              },\n              {\n                \"price\": \"0.86465\",\n                \"liquidity\": 10000000\n              }\n            ],\n            \"unitsAvailable\": {\n              \"default\": {\n                \"short\": \"624261\",\n                \"long\": \"624045\"\n              },\n              \"reduceOnly\": {\n                \"short\": \"0\",\n                \"long\": \"0\"\n              },\n              \"openOnly\": {\n                \"short\": \"624261\",\n                \"long\": \"624045\"\n              },\n              \"reduceFirst\": {\n                \"short\": \"624261\",\n                \"long\": \"624045\"\n              }\n            },\n            \"closeoutBid\": \"0.86442\",\n            \"bids\": [\n              {\n                \"price\": \"0.86446\",\n                \"liquidity\": 1000000\n              },\n              {\n                \"price\": \"0.86445\",\n                \"liquidity\": 2000000\n              },\n              {\n                \"price\": \"0.86444\",\n                \"liquidity\": 5000000\n              },\n              {\n                \"price\": \"0.86442\",\n                \"liquidity\": 10000000\n              }\n            ],\n            \"instrument\": \"EUR_GBP\",\n            \"time\": \"2016-09-29T17:07:19.994271769Z\",\n            \"closeoutAsk\": \"0.86465\",\n            \"type\": \"PRICE\"\n          }\n        ]\n      }\n    }\n\nTop_\n\nStreaming endpoints\n~~~~~~~~~~~~~~~~~~~\n\nStreaming quotes: use pricing.PricingStream.\nStreaming transactions: use transactions.TransactionsEvents.\n\nTo fetch streaming data from a stream use the following pattern:\n\n.. code-block:: python\n\n    import json\n    from oandapyV20 import API\n    from oandapyV20.exceptions import V20Error\n    from oandapyV20.endpoints.pricing import PricingStream\n\n    accountID = \"...\"\n    access_token=\"...\"\n\n    api = API(access_token=access_token, environment=\"practice\")\n\n    instruments = \"DE30_EUR,EUR_USD,EUR_JPY\"\n    s = PricingStream(accountID=accountID, params={\"instruments\":instruments})\n    try:\n        n = 0\n        for R in api.request(s):\n            print(json.dumps(R, indent=2))\n            n += 1\n            if n > 10:\n                s.terminate(\"maxrecs received: {}\".format(MAXREC))\n\n    except V20Error as e:\n        print(\"Error: {}\".format(e))\n\nCheck the 'examples' directory for more detailed examples.\n\nOutput\n``````\n\n.. code-block:: json\n\n    {\n      \"status\": \"tradeable\",\n      \"asks\": [\n        {\n          \"price\": \"10547.0\",\n          \"liquidity\": 25\n        },\n        {\n          \"price\": \"10547.2\",\n          \"liquidity\": 75\n        },\n        {\n          \"price\": \"10547.4\",\n          \"liquidity\": 150\n        }\n      ],\n      \"closeoutBid\": \"10546.6\",\n      \"bids\": [\n        {\n          \"price\": \"10547.0\",\n          \"liquidity\": 25\n        },\n        {\n          \"price\": \"10546.8\",\n          \"liquidity\": 75\n        },\n        {\n          \"price\": \"10546.6\",\n          \"liquidity\": 150\n        }\n      ],\n      \"instrument\": \"DE30_EUR\",\n      \"time\": \"2016-10-17T12:25:28.158741026Z\",\n      \"closeoutAsk\": \"10547.4\",\n      \"type\": \"PRICE\",\n    }\n    {\n      \"type\": \"HEARTBEAT\",\n      \"time\": \"2016-10-17T12:25:37.447397298Z\"\n    }\n    {\n      \"status\": \"tradeable\",\n      \"asks\": [\n        {\n          \"price\": \"114.490\",\n          \"liquidity\": 1000000\n        },\n        {\n          \"price\": \"114.491\",\n          \"liquidity\": 2000000\n        },\n        {\n          \"price\": \"114.492\",\n          \"liquidity\": 5000000\n        },\n        {\n          \"price\": \"114.494\",\n          \"liquidity\": 10000000\n        }\n      ],\n      \"closeoutBid\": \"114.469\",\n      \"bids\": [\n        {\n          \"price\": \"114.473\",\n          \"liquidity\": 1000000\n        },\n        {\n          \"price\": \"114.472\",\n          \"liquidity\": 2000000\n        },\n        {\n          \"price\": \"114.471\",\n          \"liquidity\": 5000000\n        },\n        {\n          \"price\": \"114.469\",\n          \"liquidity\": 10000000\n        }\n      ],\n      \"instrument\": \"EUR_JPY\",\n      \"time\": \"2016-10-17T12:25:40.837289374Z\",\n      \"closeoutAsk\": \"114.494\",\n      \"type\": \"PRICE\",\n    }\n    {\n      \"type\": \"HEARTBEAT\",\n      \"time\": \"2016-10-17T12:25:42.447922336Z\"\n    }\n    {\n      \"status\": \"tradeable\",\n      \"asks\": [\n        {\n          \"price\": \"1.09966\",\n          \"liquidity\": 10000000\n        },\n        {\n          \"price\": \"1.09968\",\n          \"liquidity\": 10000000\n        }\n      ],\n      \"closeoutBid\": \"1.09949\",\n      \"bids\": [\n        {\n          \"price\": \"1.09953\",\n          \"liquidity\": 10000000\n        },\n        {\n          \"price\": \"1.09951\",\n          \"liquidity\": 10000000\n        }\n      ],\n      \"instrument\": \"EUR_USD\",\n      \"time\": \"2016-10-17T12:25:43.689619691Z\",\n      \"closeoutAsk\": \"1.09970\",\n      \"type\": \"PRICE\"\n    }\n    {\n      \"status\": \"tradeable\",\n      \"asks\": [\n        {\n          \"price\": \"114.486\",\n          \"liquidity\": 1000000\n        },\n        {\n          \"price\": \"114.487\",\n          \"liquidity\": 2000000\n        },\n        {\n          \"price\": \"114.488\",\n          \"liquidity\": 5000000\n        },\n        {\n          \"price\": \"114.490\",\n          \"liquidity\": 10000000\n        }\n      ],\n      \"closeoutBid\": \"114.466\",\n      \"bids\": [\n        {\n          \"price\": \"114.470\",\n          \"liquidity\": 1000000\n        },\n        {\n          \"price\": \"114.469\",\n          \"liquidity\": 2000000\n        },\n        {\n          \"price\": \"114.468\",\n          \"liquidity\": 5000000\n        },\n        {\n          \"price\": \"114.466\",\n          \"liquidity\": 10000000\n        }\n      ],\n      \"instrument\": \"EUR_JPY\",\n      \"time\": \"2016-10-17T12:25:43.635964725Z\",\n      \"closeoutAsk\": \"114.490\",\n      \"type\": \"PRICE\"\n    }\n    {\n      \"status\": \"tradeable\",\n      \"asks\": [\n        {\n          \"price\": \"10547.3\",\n          \"liquidity\": 25\n        },\n        {\n          \"price\": \"10547.5\",\n          \"liquidity\": 75\n        },\n        {\n          \"price\": \"10547.7\",\n          \"liquidity\": 150\n        }\n      ],\n      \"closeoutBid\": \"10546.9\",\n      \"bids\": [\n        {\n          \"price\": \"10547.3\",\n          \"liquidity\": 25\n        },\n        {\n          \"price\": \"10547.1\",\n          \"liquidity\": 75\n        },\n        {\n          \"price\": \"10546.9\",\n          \"liquidity\": 150\n        }\n      ],\n      \"instrument\": \"DE30_EUR\",\n      \"time\": \"2016-10-17T12:25:44.900162113Z\",\n      \"closeoutAsk\": \"10547.7\",\n      \"type\": \"PRICE\"\n    }\n    {\n      \"status\": \"tradeable\",\n      \"asks\": [\n        {\n          \"price\": \"10547.0\",\n          \"liquidity\": 25\n        },\n        {\n          \"price\": \"10547.2\",\n          \"liquidity\": 75\n        },\n        {\n          \"price\": \"10547.4\",\n          \"liquidity\": 150\n        }\n      ],\n      \"closeoutBid\": \"10546.6\",\n      \"bids\": [\n        {\n          \"price\": \"10547.0\",\n          \"liquidity\": 25\n        },\n        {\n          \"price\": \"10546.8\",\n          \"liquidity\": 75\n        },\n        {\n          \"price\": \"10546.6\",\n          \"liquidity\": 150\n        }\n      ],\n      \"instrument\": \"DE30_EUR\",\n      \"time\": \"2016-10-17T12:25:44.963539084Z\",\n      \"closeoutAsk\": \"10547.4\",\n      \"type\": \"PRICE\"\n    }\n    {\n      \"status\": \"tradeable\",\n      \"asks\": [\n        {\n          \"price\": \"114.491\",\n          \"liquidity\": 1000000\n        },\n        {\n          \"price\": \"114.492\",\n          \"liquidity\": 2000000\n        },\n        {\n          \"price\": \"114.493\",\n          \"liquidity\": 5000000\n        },\n        {\n          \"price\": \"114.495\",\n          \"liquidity\": 10000000\n        }\n      ],\n      \"closeoutBid\": \"114.471\",\n      \"bids\": [\n        {\n          \"price\": \"114.475\",\n          \"liquidity\": 1000000\n        },\n        {\n          \"price\": \"114.474\",\n          \"liquidity\": 2000000\n        },\n        {\n          \"price\": \"114.473\",\n          \"liquidity\": 5000000\n        },\n        {\n          \"price\": \"114.471\",\n          \"liquidity\": 10000000\n        }\n      ],\n      \"instrument\": \"EUR_JPY\",\n      \"time\": \"2016-10-17T12:25:45.586100087Z\",\n      \"closeoutAsk\": \"114.495\",\n      \"type\": \"PRICE\"\n    }\n\nTop_\n\nAbout this software\n-------------------\nThe *oanda-api-v20* software is a personal project.\nI have no prior or existing relationship with OANDA.\n\nIf you have any questions regarding this software, please take a look at\nthe documentation first:\n\n * oandapyV20 : http://oanda-api-v20.readthedocs.io/en/latest/?badge=latest\n * OANDA developer docs : http://developer.oanda.com\n * examples : https://github.com/hootnot/oandapyV20-examples\n * Github: https://github.com/hootnot/oanda-api-v20 check the open and closed issues\n\nIf you still have questions/issues you can open an *issue* on Gitub: https://github.com/hootnot/oanda-api-v20\n"
  },
  {
    "path": "docs/Makefile",
    "content": "# Makefile for Sphinx documentation\n#\n\n# You can set these variables from the command line.\nSPHINXOPTS    =\nSPHINXBUILD   = sphinx-build\nPAPER         =\nBUILDDIR      = _build\n\n# Internal variables.\nPAPEROPT_a4     = -D latex_paper_size=a4\nPAPEROPT_letter = -D latex_paper_size=letter\nALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .\n# the i18n builder cannot share the environment and doctrees with the others\nI18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .\n\n.PHONY: help\nhelp:\n\t@echo \"Please use \\`make <target>' where <target> is one of\"\n\t@echo \"  html       to make standalone HTML files\"\n\t@echo \"  dirhtml    to make HTML files named index.html in directories\"\n\t@echo \"  singlehtml to make a single large HTML file\"\n\t@echo \"  pickle     to make pickle files\"\n\t@echo \"  json       to make JSON files\"\n\t@echo \"  htmlhelp   to make HTML files and a HTML help project\"\n\t@echo \"  qthelp     to make HTML files and a qthelp project\"\n\t@echo \"  applehelp  to make an Apple Help Book\"\n\t@echo \"  devhelp    to make HTML files and a Devhelp project\"\n\t@echo \"  epub       to make an epub\"\n\t@echo \"  epub3      to make an epub3\"\n\t@echo \"  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter\"\n\t@echo \"  latexpdf   to make LaTeX files and run them through pdflatex\"\n\t@echo \"  latexpdfja to make LaTeX files and run them through platex/dvipdfmx\"\n\t@echo \"  text       to make text files\"\n\t@echo \"  man        to make manual pages\"\n\t@echo \"  texinfo    to make Texinfo files\"\n\t@echo \"  info       to make Texinfo files and run them through makeinfo\"\n\t@echo \"  gettext    to make PO message catalogs\"\n\t@echo \"  changes    to make an overview of all changed/added/deprecated items\"\n\t@echo \"  xml        to make Docutils-native XML files\"\n\t@echo \"  pseudoxml  to make pseudoxml-XML files for display purposes\"\n\t@echo \"  linkcheck  to check all external links for integrity\"\n\t@echo \"  doctest    to run all doctests embedded in the documentation (if enabled)\"\n\t@echo \"  coverage   to run coverage check of the documentation (if enabled)\"\n\t@echo \"  dummy      to check syntax errors of document sources\"\n\n.PHONY: clean\nclean:\n\trm -rf $(BUILDDIR)/*\n\n.PHONY: types\ntypes:\t../oandapyV20/types/types.py\n\t@python dirstruct.py types oandapyV20.types\n\n.PHONY: html\nhtml:\ttypes\n\t$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html\n\t@echo\n\t@echo \"Build finished. The HTML pages are in $(BUILDDIR)/html.\"\n\n.PHONY: dirhtml\ndirhtml:\n\t$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml\n\t@echo\n\t@echo \"Build finished. The HTML pages are in $(BUILDDIR)/dirhtml.\"\n\n.PHONY: singlehtml\nsinglehtml:\n\t$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml\n\t@echo\n\t@echo \"Build finished. The HTML page is in $(BUILDDIR)/singlehtml.\"\n\n.PHONY: pickle\npickle:\n\t$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle\n\t@echo\n\t@echo \"Build finished; now you can process the pickle files.\"\n\n.PHONY: json\njson:\n\t$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json\n\t@echo\n\t@echo \"Build finished; now you can process the JSON files.\"\n\n.PHONY: htmlhelp\nhtmlhelp:\n\t$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp\n\t@echo\n\t@echo \"Build finished; now you can run HTML Help Workshop with the\" \\\n\t      \".hhp project file in $(BUILDDIR)/htmlhelp.\"\n\n.PHONY: qthelp\nqthelp:\n\t$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp\n\t@echo\n\t@echo \"Build finished; now you can run \"qcollectiongenerator\" with the\" \\\n\t      \".qhcp project file in $(BUILDDIR)/qthelp, like this:\"\n\t@echo \"# qcollectiongenerator $(BUILDDIR)/qthelp/OANDAREST-V20API.qhcp\"\n\t@echo \"To view the help file:\"\n\t@echo \"# assistant -collectionFile $(BUILDDIR)/qthelp/OANDAREST-V20API.qhc\"\n\n.PHONY: applehelp\napplehelp:\n\t$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp\n\t@echo\n\t@echo \"Build finished. The help book is in $(BUILDDIR)/applehelp.\"\n\t@echo \"N.B. You won't be able to view it unless you put it in\" \\\n\t      \"~/Library/Documentation/Help or install it in your application\" \\\n\t      \"bundle.\"\n\n.PHONY: devhelp\ndevhelp:\n\t$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp\n\t@echo\n\t@echo \"Build finished.\"\n\t@echo \"To view the help file:\"\n\t@echo \"# mkdir -p $$HOME/.local/share/devhelp/OANDAREST-V20API\"\n\t@echo \"# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/OANDAREST-V20API\"\n\t@echo \"# devhelp\"\n\n.PHONY: epub\nepub:\n\t$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub\n\t@echo\n\t@echo \"Build finished. The epub file is in $(BUILDDIR)/epub.\"\n\n.PHONY: epub3\nepub3:\n\t$(SPHINXBUILD) -b epub3 $(ALLSPHINXOPTS) $(BUILDDIR)/epub3\n\t@echo\n\t@echo \"Build finished. The epub3 file is in $(BUILDDIR)/epub3.\"\n\n.PHONY: latex\nlatex:\n\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex\n\t@echo\n\t@echo \"Build finished; the LaTeX files are in $(BUILDDIR)/latex.\"\n\t@echo \"Run \\`make' in that directory to run these through (pdf)latex\" \\\n\t      \"(use \\`make latexpdf' here to do that automatically).\"\n\n.PHONY: latexpdf\nlatexpdf:\n\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex\n\t@echo \"Running LaTeX files through pdflatex...\"\n\t$(MAKE) -C $(BUILDDIR)/latex all-pdf\n\t@echo \"pdflatex finished; the PDF files are in $(BUILDDIR)/latex.\"\n\n.PHONY: latexpdfja\nlatexpdfja:\n\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex\n\t@echo \"Running LaTeX files through platex and dvipdfmx...\"\n\t$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja\n\t@echo \"pdflatex finished; the PDF files are in $(BUILDDIR)/latex.\"\n\n.PHONY: text\ntext:\n\t$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text\n\t@echo\n\t@echo \"Build finished. The text files are in $(BUILDDIR)/text.\"\n\n.PHONY: man\nman:\n\t$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man\n\t@echo\n\t@echo \"Build finished. The manual pages are in $(BUILDDIR)/man.\"\n\n.PHONY: texinfo\ntexinfo:\n\t$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo\n\t@echo\n\t@echo \"Build finished. The Texinfo files are in $(BUILDDIR)/texinfo.\"\n\t@echo \"Run \\`make' in that directory to run these through makeinfo\" \\\n\t      \"(use \\`make info' here to do that automatically).\"\n\n.PHONY: info\ninfo:\n\t$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo\n\t@echo \"Running Texinfo files through makeinfo...\"\n\tmake -C $(BUILDDIR)/texinfo info\n\t@echo \"makeinfo finished; the Info files are in $(BUILDDIR)/texinfo.\"\n\n.PHONY: gettext\ngettext:\n\t$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale\n\t@echo\n\t@echo \"Build finished. The message catalogs are in $(BUILDDIR)/locale.\"\n\n.PHONY: changes\nchanges:\n\t$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes\n\t@echo\n\t@echo \"The overview file is in $(BUILDDIR)/changes.\"\n\n.PHONY: linkcheck\nlinkcheck:\n\t$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck\n\t@echo\n\t@echo \"Link check complete; look for any errors in the above output \" \\\n\t      \"or in $(BUILDDIR)/linkcheck/output.txt.\"\n\n.PHONY: doctest\ndoctest:\n\t$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest\n\t@echo \"Testing of doctests in the sources finished, look at the \" \\\n\t      \"results in $(BUILDDIR)/doctest/output.txt.\"\n\n.PHONY: coverage\ncoverage:\n\t$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage\n\t@echo \"Testing of coverage in the sources finished, look at the \" \\\n\t      \"results in $(BUILDDIR)/coverage/python.txt.\"\n\n.PHONY: xml\nxml:\n\t$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml\n\t@echo\n\t@echo \"Build finished. The XML files are in $(BUILDDIR)/xml.\"\n\n.PHONY: pseudoxml\npseudoxml:\n\t$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml\n\t@echo\n\t@echo \"Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml.\"\n\n.PHONY: dummy\ndummy:\n\t$(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILDDIR)/dummy\n\t@echo\n\t@echo \"Build finished. Dummy builder generates no files.\"\n"
  },
  {
    "path": "docs/conf.py",
    "content": "# -*- coding: utf-8 -*-\n#\n# OANDA REST-V20 API documentation build configuration file, created by\n# sphinx-quickstart on Sun Jul 10 12:57:37 2016.\n#\n# This file is execfile()d with the current directory set to its\n# containing dir.\n#\n# Note that not all possible configuration values are present in this\n# autogenerated file.\n#\n# All configuration values have a default; values that are commented out\n# serve to show the default.\n\n# If extensions (or modules to document with autodoc) are in another directory,\n# add these directories to sys.path here. If the directory is relative to the\n# documentation root, use os.path.abspath to make it absolute, like shown here.\n#\nimport os\nimport sys\nsys.path.insert(0, os.path.abspath('oandapyV20'))\nimport oandapyV20\n\n# -- General configuration ------------------------------------------------\n\n# If your documentation needs a minimal Sphinx version, state it here.\n#\n# needs_sphinx = '1.0'\n\n# Add any Sphinx extension module names here, as strings. They can be\n# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom\n# ones.\nextensions = [\n    'sphinx.ext.autodoc',\n    'sphinx.ext.napoleon',\n]\n\n# Add any paths that contain templates here, relative to this directory.\ntemplates_path = ['_templates']\n\n# The suffix(es) of source filenames.\n# You can specify multiple suffix as a list of string:\n#\n# source_suffix = ['.rst', '.md']\nsource_suffix = '.rst'\n\n# The encoding of source files.\n#\n# source_encoding = 'utf-8-sig'\n\n# The master toctree document.\nmaster_doc = 'index'\n\n# General information about the project.\nproject = getattr(sys.modules[\"oandapyV20\"], \"__title__\")\ncopyright = getattr(sys.modules[\"oandapyV20\"], \"__copyright__\")\nauthor = getattr(sys.modules[\"oandapyV20\"], \"__author__\")\n\n# The version info for the project you're documenting, acts as replacement for\n# |version| and |release|, also used in various other places throughout the\n# built documents.\n#\n# The short X.Y version.\nversion = getattr(sys.modules[\"oandapyV20\"], \"__version__\")\n# The full version, including alpha/beta/rc tags.\nrelease = getattr(sys.modules[\"oandapyV20\"], \"__version__\")\n\n# The language for content autogenerated by Sphinx. Refer to documentation\n# for a list of supported languages.\n#\n# This is also used if you do content translation via gettext catalogs.\n# Usually you set \"language\" from the command line for these cases.\nlanguage = None\n\n# There are two options for replacing |today|: either, you set today to some\n# non-false value, then it is used:\n#\n# today = ''\n#\n# Else, today_fmt is used as the format for a strftime call.\n#\n# today_fmt = '%B %d, %Y'\n\n# List of patterns, relative to source directory, that match files and\n# directories to ignore when looking for source files.\n# This patterns also effect to html_static_path and html_extra_path\nexclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']\n\n# The reST default role (used for this markup: `text`) to use for all\n# documents.\n#\n# default_role = None\n\n# If true, '()' will be appended to :func: etc. cross-reference text.\n#\n# add_function_parentheses = True\n\n# If true, the current module name will be prepended to all description\n# unit titles (such as .. function::).\n#\n# add_module_names = True\n\n# If true, sectionauthor and moduleauthor directives will be shown in the\n# output. They are ignored by default.\n#\n# show_authors = False\n\n# The name of the Pygments (syntax highlighting) style to use.\npygments_style = 'sphinx'\n\n# A list of ignored prefixes for module index sorting.\n# modindex_common_prefix = []\n\n# If true, keep warnings as \"system message\" paragraphs in the built documents.\n# keep_warnings = False\n\n# If true, `todo` and `todoList` produce output, else they produce nothing.\ntodo_include_todos = False\n\n\n# -- Options for HTML output ----------------------------------------------\n\n# The theme to use for HTML and HTML Help pages.  See the documentation for\n# a list of builtin themes.\n#\nhtml_theme = 'default'\n\n# Theme options are theme-specific and customize the look and feel of a theme\n# further.  For a list of options available for each theme, see the\n# documentation.\n#\n# html_theme_options = {}\n\n# Add any paths that contain custom themes here, relative to this directory.\n# html_theme_path = []\n\n# The name for this set of Sphinx documents.\n# \"<project> v<release> documentation\" by default.\n#\n# html_title = u'OANDA REST-V20 API v0.1.0'\n\n# A shorter title for the navigation bar.  Default is the same as html_title.\n#\n# html_short_title = None\n\n# The name of an image file (relative to this directory) to place at the top\n# of the sidebar.\n#\n# html_logo = None\n\n# The name of an image file (relative to this directory) to use as a favicon of\n# the docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32\n# pixels large.\n#\n# html_favicon = None\n\n# Add any paths that contain custom static files (such as style sheets) here,\n# relative to this directory. They are copied after the builtin static files,\n# so a file named \"default.css\" will overwrite the builtin \"default.css\".\nhtml_static_path = ['_static']\n\n# Add any extra paths that contain custom files (such as robots.txt or\n# .htaccess) here, relative to this directory. These files are copied\n# directly to the root of the documentation.\n#\n# html_extra_path = []\n\n# If not None, a 'Last updated on:' timestamp is inserted at every page\n# bottom, using the given strftime format.\n# The empty string is equivalent to '%b %d, %Y'.\n#\n# html_last_updated_fmt = None\n\n# If true, SmartyPants will be used to convert quotes and dashes to\n# typographically correct entities.\n#\n# html_use_smartypants = True\n\n# Custom sidebar templates, maps document names to template names.\n#\n# html_sidebars = {}\n\n# Additional templates that should be rendered to pages, maps page names to\n# template names.\n#\n# html_additional_pages = {}\n\n# If false, no module index is generated.\n#\n# html_domain_indices = True\n\n# If false, no index is generated.\n#\n# html_use_index = True\n\n# If true, the index is split into individual pages for each letter.\n#\n# html_split_index = False\n\n# If true, links to the reST sources are added to the pages.\n#\n# html_show_sourcelink = True\n\n# If true, \"Created using Sphinx\" is shown in the HTML footer. Default is True.\n#\n# html_show_sphinx = True\n\n# If true, \"(C) Copyright ...\" is shown in the HTML footer. Default is True.\n#\n# html_show_copyright = True\n\n# If true, an OpenSearch description file will be output, and all pages will\n# contain a <link> tag referring to it.  The value of this option must be the\n# base URL from which the finished HTML is served.\n#\n# html_use_opensearch = ''\n\n# This is the file name suffix for HTML files (e.g. \".xhtml\").\n# html_file_suffix = None\n\n# Language to be used for generating the HTML full-text search index.\n# Sphinx supports the following languages:\n#   'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'\n#   'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr', 'zh'\n#\n# html_search_language = 'en'\n\n# A dictionary with options for the search language support, empty by default.\n# 'ja' uses this config value.\n# 'zh' user can custom change `jieba` dictionary path.\n#\n# html_search_options = {'type': 'default'}\n\n# The name of a javascript file (relative to the configuration directory) that\n# implements a search results scorer. If empty, the default will be used.\n#\n# html_search_scorer = 'scorer.js'\n\n# Output file base name for HTML help builder.\nhtmlhelp_basename = 'OANDAREST-V20APIdoc'\n\n# -- Options for LaTeX output ---------------------------------------------\n\nlatex_elements = {\n     # The paper size ('letterpaper' or 'a4paper').\n     #\n     # 'papersize': 'letterpaper',\n\n     # The font size ('10pt', '11pt' or '12pt').\n     #\n     # 'pointsize': '10pt',\n\n     # Additional stuff for the LaTeX preamble.\n     #\n     # 'preamble': '',\n\n     # Latex figure (float) alignment\n     #\n     # 'figure_align': 'htbp',\n}\n\n# Grouping the document tree into LaTeX files. List of tuples\n# (source start file, target name, title,\n#  author, documentclass [howto, manual, or own class]).\nlatex_documents = [\n    (master_doc, 'OANDAREST-V20API.tex', u'OANDA REST-V20 API Documentation',\n     u'Feite Brekeveld', 'manual'),\n]\n\n# The name of an image file (relative to this directory) to place at the top of\n# the title page.\n#\n# latex_logo = None\n\n# For \"manual\" documents, if this is true, then toplevel headings are parts,\n# not chapters.\n#\n# latex_use_parts = False\n\n# If true, show page references after internal links.\n#\n# latex_show_pagerefs = False\n\n# If true, show URL addresses after external links.\n#\n# latex_show_urls = False\n\n# Documents to append as an appendix to all manuals.\n#\n# latex_appendices = []\n\n# If false, no module index is generated.\n#\n# latex_domain_indices = True\n\n\n# -- Options for manual page output ---------------------------------------\n\n# One entry per manual page. List of tuples\n# (source start file, name, description, authors, manual section).\nman_pages = [\n    (master_doc, 'oanda-api-v20', u'OANDA REST-V20 API Documentation',\n     [author], 1)\n]\n\n# If true, show URL addresses after external links.\n#\n# man_show_urls = False\n\n\n# -- Options for Texinfo output -------------------------------------------\n\n# Grouping the document tree into Texinfo files. List of tuples\n# (source start file, target name, title, author,\n#  dir menu entry, description, category)\ntexinfo_documents = [\n    (master_doc, 'OANDAREST-V20API', u'OANDA REST-V20 API Documentation',\n     author, 'OANDAREST-V20API', 'One line description of project.',\n     'Miscellaneous'),\n]\n\n# Documents to append as an appendix to all manuals.\n#\n# texinfo_appendices = []\n\n# If false, no module index is generated.\n#\n# texinfo_domain_indices = True\n\n# How to display URL addresses: 'footnote', 'no', or 'inline'.\n#\n# texinfo_show_urls = 'footnote'\n\n# If true, do not generate a @detailmenu in the \"Top\" node's menu.\n#\n# texinfo_no_detailmenu = False\n# Napoleon settings\nnapoleon_google_docstring = True\nnapoleon_numpy_docstring = True\n# napoleon_include_private_with_doc = False\n# napoleon_include_special_with_doc = True\nnapoleon_use_admonition_for_examples = False\nnapoleon_use_admonition_for_notes = False\nnapoleon_use_admonition_for_references = False\nnapoleon_use_ivar = False\nnapoleon_use_param = True\nnapoleon_use_rtype = True\n\non_rtd = os.environ.get('READTHEDOCS', None) == 'True'\n\n# custom directive (stackoverflow.com: 7250659)\nfrom os.path import basename\n\ntry:\n    from StringIO import StringIO\nexcept ImportError:\n    from io import StringIO\n\nfrom docutils import nodes, statemachine\nfrom docutils.parsers.rst import Directive\n\nclass ExecDirective(Directive):\n    \"\"\"Execute the specified python code and insert the output into the document\"\"\"\n    has_content = True\n\n    def run(self):\n        oldStdout, sys.stdout = sys.stdout, StringIO()\n\n        tab_width = self.options.get('tab-width', self.state.document.settings.tab_width)\n        source = self.state_machine.input_lines.source(self.lineno - self.state_machine.input_offset - 1)\n\n        try:\n            exec('\\n'.join(self.content))\n            text = sys.stdout.getvalue()\n            lines = statemachine.string2lines(text, tab_width, convert_whitespace=True)\n            self.state_machine.insert_input(lines, source)\n            return []\n        except Exception:\n            return [nodes.error(None, nodes.paragraph(text = \"Unable to execute python code at %s:%d:\" % (basename(source), self.lineno)), nodes.paragraph(text = str(sys.exc_info()[1])))]\n        finally:\n            sys.stdout = oldStdout\n\ndef setup(app):\n    app.add_directive('exec', ExecDirective)\n\nif not on_rtd:  # only import and set the theme if we're building docs locally\n    import sphinx_rtd_theme\n    html_theme = 'sphinx_rtd_theme'\n    html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]\n"
  },
  {
    "path": "docs/contrib/factories/instrumentscandlesfactory.rst",
    "content": "InstrumentsCandlesFactory\n-------------------------\n\n.. automodule:: oandapyV20.contrib.factories\n   :members:\n"
  },
  {
    "path": "docs/contrib/factories.rst",
    "content": "Factories\n---------\n\nThe :mod:`oandapyV20.contrib.factories` module contains several classes /\nmethods that can be used optionally to generate requests.\n\n\n.. toctree::\n   :maxdepth: 4\n   :glob:\n\n   factories/*\n"
  },
  {
    "path": "docs/contrib/generic/generic.rst",
    "content": "granularity_to_time\n-------------------\n\n.. automodule:: oandapyV20.contrib.generic\n   :members:\n"
  },
  {
    "path": "docs/contrib/generic.rst",
    "content": "Generic\n---------\n\nThe :mod:`oandapyV20.contrib.generic` module contains several classes /\nmethods that serve a generic purpose.\n\n\n.. toctree::\n   :maxdepth: 4\n   :glob:\n\n   generic/*\n"
  },
  {
    "path": "docs/contrib/orders/limitorderrequest.rst",
    "content": "LimitOrderRequest\n------------------\n\n.. autoclass:: oandapyV20.contrib.requests.LimitOrderRequest\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/contrib/orders/marketorderrequest.rst",
    "content": "MarketOrderRequest\n------------------\n\n.. autoclass:: oandapyV20.contrib.requests.MarketOrderRequest\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/contrib/orders/mitorderrequest.rst",
    "content": "MITOrderRequest\n---------------\n\n.. autoclass:: oandapyV20.contrib.requests.MITOrderRequest\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/contrib/orders/positionscloserequest.rst",
    "content": "PositionCloseRequest\n--------------------\n\n.. autoclass:: oandapyV20.contrib.requests.PositionCloseRequest\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/contrib/orders/stoplossorderrequest.rst",
    "content": "StopLossOrderRequest\n--------------------\n\n.. autoclass:: oandapyV20.contrib.requests.StopLossOrderRequest\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/contrib/orders/stoporderrequest.rst",
    "content": "StopOrderRequest\n----------------\n\n.. autoclass:: oandapyV20.contrib.requests.StopOrderRequest\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/contrib/orders/takeprofitorderrequest.rst",
    "content": "TakeProfitOrderRequest\n----------------------\n\n.. autoclass:: oandapyV20.contrib.requests.TakeProfitOrderRequest\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/contrib/orders/tradecloserequest.rst",
    "content": "TradeCloseRequest\n-----------------\n\n.. autoclass:: oandapyV20.contrib.requests.TradeCloseRequest\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/contrib/orders/trailingstoplossorderrequest.rst",
    "content": "TrailingStopLossOrderRequest\n----------------------------\n\n.. autoclass:: oandapyV20.contrib.requests.TrailingStopLossOrderRequest\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/contrib/orders.rst",
    "content": "Order Classes\n-------------\n\nThe :mod:`oandapyV20.contrib.requests` module contains several classes \nthat can be used optionally when creating Order Requests.\n\nWhen creating an order to create a position, it is possible to create\ndependant orders that will be triggered when the position gets filled.\nThis goes typically for *Take Profit* and *Stop Loss*.\n\nThese order specifications and additional data that goes with these order\nspecifications can be created by the contrib.requests.*Order* classes and\nthe contrib.requests.*Details classes. \n\n.. toctree::\n   :maxdepth: 4\n   :glob:\n\n   orders/*\n"
  },
  {
    "path": "docs/contrib/support/clientextensions.rst",
    "content": "Client Extensions\n~~~~~~~~~~~~~~~~~\n\nClient extensions can be used optionally on Order Requests. It allows\na client to set a custom ID, Tag and/or Comment.\n\n.. autoclass:: oandapyV20.contrib.requests.ClientExtensions\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/contrib/support/stoplossdetails.rst",
    "content": "StopLossDetails\n~~~~~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.contrib.requests.StopLossDetails\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/contrib/support/takeprofitdetails.rst",
    "content": "TakeProfitDetails\n~~~~~~~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.contrib.requests.TakeProfitDetails\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/contrib/support/trailingstoplossdetails.rst",
    "content": "TrailingStopLossDetails\n~~~~~~~~~~~~~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.contrib.requests.TrailingStopLossDetails\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/contrib/support.rst",
    "content": "support classes\n---------------\n\nThe :mod:`oandapyV20.contrib.requests` module contains several classes \nthat can be used optionally when creating Order Requests.\n\nWhen creating an order to create a position, it is possible to create\ndependant orders that will be triggered when the position gets filled.\nThis goes typically for *Take Profit* and *Stop Loss*.\n\nThese order specifications and additional data that goes with these order\nspecifications can be created by the contrib.requests.*Order* classes and\nthe contrib.requests.*Details classes. \n\n.. toctree::\n   :maxdepth: 4\n   :glob:\n\n   support/*\n"
  },
  {
    "path": "docs/dirstruct.py",
    "content": "# -*- coding: utf8 -*-\n\"\"\"dirstruct.\n\ngenerate document directory structure.\n\"\"\"\nimport sys\nimport os\nimport inspect\nfrom importlib import import_module\n\n\ndef get_classes(modName):\n    \"\"\"return a list of all classes in a module.\"\"\"\n    classNames = []\n    for name, obj in inspect.getmembers(sys.modules[modName]):\n        if inspect.isclass(obj):\n            classNames.append(name)\n\n    return classNames\n\n\nif __name__ == \"__main__\":\n\n    destDir = sys.argv[1]\n    modToDoc = sys.argv[2]\n    import_module(modToDoc)\n\n    if not os.path.exists(destDir):\n        os.makedirs(destDir)\n\n    for cls in get_classes(modToDoc):\n        with open(os.path.join(destDir, \"{}.rst\".format(cls)), \"w\") as F:\n            #    :show-inheritance:\\n\n            F.write(\"\"\"{cls}\\n\"\"\"\n                    \"\"\"{ul}\\n\"\"\"\n                    \"\"\"\\n\"\"\"\n                    \"\"\".. autoclass:: {mod}.{cls}\\n\"\"\"\n                    \"\"\"    :members:\\n\"\"\"\n                    \"\"\"    :undoc-members:\\n\"\"\"\n                    \"\"\"    :inherited-members:\\n\"\"\"\n                    \"\"\"    :special-members: __init__\\n\"\"\".format(\n                        cls=cls,\n                        ul=len(cls)*\"~\",\n                        mod=modToDoc))\n"
  },
  {
    "path": "docs/endpoints/accounts/accountchanges.rst",
    "content": "AccountChanges\n~~~~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.accounts.AccountChanges\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/accounts/accountconfiguration.rst",
    "content": "AccountConfiguration\n~~~~~~~~~~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.accounts.AccountConfiguration\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/accounts/accountdetails.rst",
    "content": "AccountDetails\n~~~~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.accounts.AccountDetails\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/accounts/accountinstruments.rst",
    "content": "AccountInstruments\n~~~~~~~~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.accounts.AccountInstruments\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/accounts/accountlist.rst",
    "content": "AccountList\n~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.accounts.AccountList\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/accounts/accountsummary.rst",
    "content": "AccountSummary\n~~~~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.accounts.AccountSummary\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/accounts.rst",
    "content": "oandapyV20.endpoints.accounts\n-----------------------------\n\n.. toctree::\n   :maxdepth: 4\n   :glob:\n\n   accounts/*\n"
  },
  {
    "path": "docs/endpoints/forexlabs/autochartist.rst",
    "content": "Autochartist\n~~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.forexlabs.Autochartist\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/forexlabs/calendar.rst",
    "content": "Calendar\n~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.forexlabs.Calendar\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/forexlabs/commitmentsoftraders.rst",
    "content": "CommitmentsOfTraders\n~~~~~~~~~~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.forexlabs.CommitmentsOfTraders\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/forexlabs/historicalpositionratios.rst",
    "content": "HistoricalPositionRatios\n~~~~~~~~~~~~~~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.forexlabs.HistoricalPositionRatios\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/forexlabs/orderbookdata.rst",
    "content": "OrderbookData\n~~~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.forexlabs.OrderbookData\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/forexlabs/spreads.rst",
    "content": "Spreads\n~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.forexlabs.Spreads\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/forexlabs.rst",
    "content": "oandapyV20.endpoints.forexlabs\n------------------------------\n\n.. toctree::\n   :maxdepth: 4\n   :glob:\n\n   forexlabs/*\n"
  },
  {
    "path": "docs/endpoints/instruments/instrumentlist.rst",
    "content": "InstrumentsCandles\n~~~~~~~~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.instruments.InstrumentsCandles\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/instruments/instrumentorderbook.rst",
    "content": "InstrumentsOrderBook\n~~~~~~~~~~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.instruments.InstrumentsOrderBook\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/instruments/instrumentpositionbook.rst",
    "content": "InstrumentsPositionBook\n~~~~~~~~~~~~~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.instruments.InstrumentsPositionBook\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/instruments.rst",
    "content": "oandapyV20.endpoints.instruments\n--------------------------------\n\n.. toctree::\n   :maxdepth: 4\n   :glob:\n\n   instruments/*\n"
  },
  {
    "path": "docs/endpoints/orders/ordercancel.rst",
    "content": "OrderCancel\n~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.orders.OrderCancel\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/orders/orderclientextensions.rst",
    "content": "OrderClientExtensions\n~~~~~~~~~~~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.orders.OrderClientExtensions\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/orders/ordercreate.rst",
    "content": "OrderCreate\n~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.orders.OrderCreate\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/orders/orderdetails.rst",
    "content": "OrderDetails\n~~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.orders.OrderDetails\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/orders/orderlist.rst",
    "content": "OrderList\n~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.orders.OrderList\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/orders/orderreplace.rst",
    "content": "OrderReplace\n~~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.orders.OrderReplace\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/orders/orderspending.rst",
    "content": "OrdersPending\n~~~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.orders.OrdersPending\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/orders.rst",
    "content": "oandapyV20.endpoints.orders\n---------------------------\n\n.. toctree::\n   :maxdepth: 4\n   :glob:\n\n   orders/*\n"
  },
  {
    "path": "docs/endpoints/positions/openpositions.rst",
    "content": "OpenPositions\n~~~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.positions.OpenPositions\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/positions/positionclose.rst",
    "content": "PositionClose\n~~~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.positions.PositionClose\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/positions/positiondetails.rst",
    "content": "PositionDetails\n~~~~~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.positions.PositionDetails\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/positions/positionlist.rst",
    "content": "PositionList\n~~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.positions.PositionList\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/positions.rst",
    "content": "oandapyV20.endpoints.positions\n------------------------------\n\n.. toctree::\n   :maxdepth: 4\n   :glob:\n\n   positions/*\n"
  },
  {
    "path": "docs/endpoints/pricing/pricinginfo.rst",
    "content": "PricingInfo\n~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.pricing.PricingInfo\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/pricing/pricingstream.rst",
    "content": "PricingStream\n~~~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.pricing.PricingStream\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/pricing.rst",
    "content": "oandapyV20.endpoints.pricing\n----------------------------\n\n.. toctree::\n   :maxdepth: 4\n   :glob:\n\n   pricing/*\n"
  },
  {
    "path": "docs/endpoints/trades/opentrades.rst",
    "content": "OpenTrades\n~~~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.trades.OpenTrades\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/trades/tradeCRCDO.rst",
    "content": "TradeCRCDO\n~~~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.trades.TradeCRCDO\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/trades/tradeclientextensions.rst",
    "content": "TradeClientExtensions\n~~~~~~~~~~~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.trades.TradeClientExtensions\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/trades/tradeclose.rst",
    "content": "TradeClose\n~~~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.trades.TradeClose\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/trades/tradedetails.rst",
    "content": "TradeDetails\n~~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.trades.TradeDetails\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/trades/tradeslist.rst",
    "content": "TradesList\n~~~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.trades.TradesList\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/trades.rst",
    "content": "oandapyV20.endpoints.trades\n---------------------------\n\n.. toctree::\n   :maxdepth: 4\n   :glob:\n\n   trades/*\n"
  },
  {
    "path": "docs/endpoints/transactions/transactiondetails.rst",
    "content": "TransactionDetails\n~~~~~~~~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.transactions.TransactionDetails\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/transactions/transactionidrange.rst",
    "content": "TransactionIDRange\n~~~~~~~~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.transactions.TransactionIDRange\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/transactions/transactionlist.rst",
    "content": "TransactionList\n~~~~~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.transactions.TransactionList\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/transactions/transactionssinceid.rst",
    "content": "TransactionsSinceID\n~~~~~~~~~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.transactions.TransactionsSinceID\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/transactions/transactionsstream.rst",
    "content": "TransactionsStream\n~~~~~~~~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.endpoints.transactions.TransactionsStream\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/endpoints/transactions.rst",
    "content": "oandapyV20.endpoints.transactions\n---------------------------------\n\n.. toctree::\n   :maxdepth: 4\n   :glob:\n\n   transactions/*\n"
  },
  {
    "path": "docs/examples.rst",
    "content": "Examples\n--------\n\nExamples can be found in the examples repositiory on github: examplesrepo_.\n\n.. _examplesrepo: https://github.com/hootnot/oandapyV20-examples\n\n\nExample for trades-endpoints\n````````````````````````````\n\nTake the script below and name it 'trades.py'. From the shell:\n\n::\n\n    hootnot@dev:~/test$ python trades.py list\n    hootnot@dev:~/test$ python trades.py open\n    hootnot@dev:~/test$ python trades.py details <id1> [<id2> ...]\n    hootnot@dev:~/test$ python trades.py close <id1> <numunits> [<id2> <numunits>...]\n    hootnot@dev:~/test$ python trades.py clext <id1> [<id2> ...]\n    hootnot@dev:~/test$ python trades.py crc_do <id1> <takeprofit> <stoploss> [<id2> ...]\n\n\n.. code-block:: python\n   \n    # use of the Trades{..} classes\n    import json\n    import requests\n    from oandapyV20 import API\n    \n    \n    import oandapyV20.endpoints.trades as trades\n    import sys\n \n    access_token = \"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy\"\n    accountID = \"zzz-zzzz-zzzzz\"\n\n    api = API(access_token=access_token)\n \n    if chc == 'list':\n       r = trades.TradesList(accountID)\n       rv = api.request(r)\n       print(\"RESP:\\n{} \".format(json.dumps(rv, indent=2)))\n \n    if chc == 'open':\n       r = trades.OpenTrades(accountID)\n       rv = api.request(r)\n       print(\"RESP:\\n{} \".format(json.dumps(rv, indent=2)))\n       tradeIDs = [o[\"id\"] for o in rv[\"trades\"]]\n       print(\"TRADE IDS: {}\".format(tradeIDs))\n \n    if chc == 'details':\n       for O in sys.argv[2:]:\n           r = trades.TradeDetails(accountID, tradeID=O)\n           rv = api.request(r)\n           print(\"RESP:\\n{} \".format(json.dumps(rv, indent=2)))\n \n    if chc == 'close':\n       X = iter(sys.argv[2:])\n       for O in X:\n           cfg = { \"units\": X.next() }\n           r = trades.TradeClose(accountID, tradeID=O, data=cfg)\n           rv = api.request(r)\n           print(\"RESP:\\n{} \".format(json.dumps(rv, indent=2)))\n \n    if chc == 'cltext':\n       for O in sys.argv[2:]:  # tradeIDs\n           cfg = { \"clientExtensions\": {\n                   \"id\": \"myID{}\".format(O),\n                   \"comment\": \"myComment\",\n                }\n             }\n           r = trades.TradeClientExtensions(accountID, tradeID=O, data=cfg)\n           rv = api.request(r)\n           print(\"RESP:\\n{} \".format(json.dumps(rv, indent=2)))\n \n    if chc == 'crc_do':\n       X = iter(sys.argv[2:])\n       for O in X:\n           cfg = {\n                   \"takeProfit\": {\n                     \"timeInForce\": \"GTC\",\n                     \"price\": X.next(),\n                   },\n                   \"stopLoss\": {\n                     \"timeInForce\": \"GTC\",\n                     \"price\": X.next()\n                   }\n             }\n           r = trades.TradeCRCDO(accountID, tradeID=O, data=cfg)\n           rv = api.request(r)\n           print(\"RESP:\\n{} \".format(json.dumps(rv, indent=2)))\n"
  },
  {
    "path": "docs/index.rst",
    "content": ".. OANDA REST-V20 API documentation master file, created by\n   sphinx-quickstart on Sun Jul 10 12:57:37 2016.\n   You can adapt this file completely to your liking, but it should at least\n   contain the root `toctree` directive.\n\nThe oandapyV20 REST-V20 API wrapper documentation\n=================================================\n\nContents:\n\n.. toctree::\n   :maxdepth: 2\n   :caption: oandapyV20 REST-V20 API wrapper\n\n   installation\n   oanda-api-v20\n\n   oandapyV20.endpoints\n   oandapyV20.definitions\n   oandapyV20.types\n   oandapyV20.contrib\n   examples\n\n.. modules\n   oandapyV20\n\n\n\n\nIndices and tables\n==================\n\n* :ref:`genindex`\n* :ref:`modindex`\n* :ref:`search`\n\n"
  },
  {
    "path": "docs/installation.rst",
    "content": "Introduction\n============\n\nThe :mod:`oandapyV20` package offers an API to the OANDA V20 REST service.\nTo use the REST-API-service you will need a *token* and an *account*. This\napplies for both *live*  and *practice* accounts. For details check oanda.com_.\n\n.. _oanda.com: https://oanda.com\n\n\nInstall\n-------\n\nInstall the pypi package with pip::\n\n    $ pip install oandapyV20\n\nOr alternatively install the latest development version from github::\n\n    $ pip install git+https://github.com/hootnot/oanda-api-v20.git\n\n\nYou may consider using *virtualenv* to create isolated Python environments. Python 3.4 has *pyvenv* providing\nthe same kind of functionality.\n\n\nDownload from Github\n--------------------\n\nIf you want to run the tests, download the source from github::\n\n\n    $ git clone https://github.com/hootnot/oanda-api-v20.git\n    $ cd oanda-api-v20\n    $ python setup.py test\n    $ python setup.py install\n"
  },
  {
    "path": "docs/oanda-api-v20.rst",
    "content": "Interface OANDA's REST-V20\n==========================\n\nThe client\n----------\n\nThe :mod:`oandapyV20` package contains a client class, :class:`oandapyV20.API`, to\ncommunicate with the REST-V20 interface. It processes requests that\ncan be created from the endpoint classes.\nFor it's communication it relies on: :py:mod:`requests`\n(requests_).\n\n.. _requests: http://docs.python-requests.org/en/master/\n\nThe client keeps no state of a requests.\nThe response of a request is assigned to the request instance. The response\nis also returned as a return value by the client.\n\n.. autoclass:: oandapyV20.API\n      :inherited-members:\n      :show-inheritance:\n      :special-members: __init__\n\nExceptions\n----------\n\n.. autoclass:: oandapyV20.V20Error\n      :inherited-members:\n      :show-inheritance:\n      :special-members: __init__\n\nLogging\n-------\n\nThe :mod:`oandapyV20` package has `logging` integrated. Logging can be\nsimply applied by enabling a `logger`.\nThe example below will log INFO-level logging to the file *v20.log*.\nFor details check the :py:mod:`logger` module in the standard Python\ndocumentation.\n\n\n.. code-block:: python\n\n\n    # code snippet\n    from oandapyV20 import API\n    import oandapyV20.endpoints.orders as orders\n    from oandapyV20.exceptions import V20Error\n    from exampleauth import exampleAuth\n    import logging\n\n    logging.basicConfig(\n        filename=\"v20.log\",\n        level=logging.INFO,\n        format='%(asctime)s [%(levelname)s] %(name)s : %(message)s',\n    )\n\n    accountID, token = exampleAuth()\n    ...\n\nResulting loglines:\n\n.. code-block:: text\n\n    2016-10-22 17:50:37,988 [INFO] oandapyV20.oandapyV20 : setting up API-client for environment practice\n    2016-10-22 17:50:37,990 [INFO] oandapyV20.oandapyV20 : performing request https://api-fxpractice.oanda.com/v3/accounts/101-004-1435156-001/orders\n    2016-10-22 17:50:37,998 [INFO] requests.packages.urllib3.connectionpool : Starting new HTTPS connection (1): api-fxpractice.oanda.com\n    2016-10-22 17:50:38,866 [INFO] oandapyV20.oandapyV20 : performing request https://api-fxpractice.oanda.com/v3/accounts/101-004-1435156-001/orders\n    2016-10-22 17:50:39,066 [ERROR] oandapyV20.oandapyV20 : request https://api-fxpractice.oanda.com/v3/accounts/101-004-1435156-001/orders failed [400,{\"errorMessage\":\"Invalid value specified for 'order.instrument'\"}]\n"
  },
  {
    "path": "docs/oandapyV20.contrib.rst",
    "content": "oandapyV20.contrib\n==================\n\n.. toctree::\n   :maxdepth: 4\n   :glob:\n\n   contrib/*\n"
  },
  {
    "path": "docs/oandapyV20.definitions.accounts.rst",
    "content": "oandapyV20.definitions.accounts\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n.. automodule:: oandapyV20.definitions.accounts\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __getitem__\n"
  },
  {
    "path": "docs/oandapyV20.definitions.instruments.rst",
    "content": "oandapyV20.definitions.instruments\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n.. automodule:: oandapyV20.definitions.instruments\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __getitem__\n"
  },
  {
    "path": "docs/oandapyV20.definitions.orders.rst",
    "content": "oandapyV20.definitions.orders\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n.. automodule:: oandapyV20.definitions.orders\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __getitem__\n"
  },
  {
    "path": "docs/oandapyV20.definitions.pricing.rst",
    "content": "oandapyV20.definitions.pricing\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n.. automodule:: oandapyV20.definitions.pricing\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __getitem__\n"
  },
  {
    "path": "docs/oandapyV20.definitions.rst",
    "content": "oandapyV20.definitions\n======================\n\nThe :mod:`oandapyV20.definitions` module holds all the definitions as in the\ndefinitions section of the REST-V20 specs of OANDA, see developer.oanda.com_.\n\n.. _developer.oanda.com: http://developer.oanda.com\n\n\n.. toctree::\n   :maxdepth: 3\n\n   oandapyV20.definitions.accounts\n   oandapyV20.definitions.instruments\n   oandapyV20.definitions.orders\n   oandapyV20.definitions.pricing\n   oandapyV20.definitions.trades\n   oandapyV20.definitions.transactions\n"
  },
  {
    "path": "docs/oandapyV20.definitions.trades.rst",
    "content": "oandapyV20.definitions.trades\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n.. automodule:: oandapyV20.definitions.trades\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __getitem__\n"
  },
  {
    "path": "docs/oandapyV20.definitions.transactions.rst",
    "content": "oandapyV20.definitions.transactions\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n.. automodule:: oandapyV20.definitions.transactions\n    :members:\n    :undoc-members:\n    :show-inheritance:\n    :special-members: __getitem__\n"
  },
  {
    "path": "docs/oandapyV20.endpoints.rst",
    "content": "oandapyV20.endpoints\n====================\n\n.. toctree::\n   :maxdepth: 4\n   :glob:\n\n   endpoints/*\n"
  },
  {
    "path": "docs/oandapyV20.types.rst",
    "content": "oandapyV20.types\n================\n\nThe :mod:`oandapyV20.types` module contains the types representing the types\nthat are used in the API-specs of OANDA, check developer.oanda.com_.\nThese types offer a convenient interface between Python types and\nthe types used in the REST-API.\n\n.. _developer.oanda.com: http://developer.oanda.com\n\nTake for instance the `PriceValue` type. It is the string representation of\na float.\n\n.. code-block:: python\n\n    from oandapyV20.types import PriceValue\n\n    pv1 = PriceValue(122.345)\n    pv2 = PriceValue(\"122.345\")\n    pv1.value\n    \"122.345\"\n    pv1.value == pv2.value\n    True\n\nRegardless the value we instantiate it with, a float or a string,\nthe PriceValue instance will allways be a string value.\n\nThe types also validate the values passed. Invalid values will raise an\nexception.\n\n\n.. toctree::\n   :maxdepth: 4\n   :glob:\n\n   types/*\n"
  },
  {
    "path": "docs/types/AccountID.rst",
    "content": "AccountID\n~~~~~~~~~\n\n.. autoclass:: oandapyV20.types.AccountID\n    :members:\n    :undoc-members:\n    :inherited-members:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/types/AccountUnits.rst",
    "content": "AccountUnits\n~~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.types.AccountUnits\n    :members:\n    :undoc-members:\n    :inherited-members:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/types/ClientComment.rst",
    "content": "ClientComment\n~~~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.types.ClientComment\n    :members:\n    :undoc-members:\n    :inherited-members:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/types/ClientID.rst",
    "content": "ClientID\n~~~~~~~~\n\n.. autoclass:: oandapyV20.types.ClientID\n    :members:\n    :undoc-members:\n    :inherited-members:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/types/ClientTag.rst",
    "content": "ClientTag\n~~~~~~~~~\n\n.. autoclass:: oandapyV20.types.ClientTag\n    :members:\n    :undoc-members:\n    :inherited-members:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/types/DateTime.rst",
    "content": "DateTime\n~~~~~~~~\n\n.. autoclass:: oandapyV20.types.DateTime\n    :members:\n    :undoc-members:\n    :inherited-members:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/types/OrderID.rst",
    "content": "OrderID\n~~~~~~~\n\n.. autoclass:: oandapyV20.types.OrderID\n    :members:\n    :undoc-members:\n    :inherited-members:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/types/OrderIdentifier.rst",
    "content": "OrderIdentifier\n~~~~~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.types.OrderIdentifier\n    :members:\n    :undoc-members:\n    :inherited-members:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/types/OrderSpecifier.rst",
    "content": "OrderSpecifier\n~~~~~~~~~~~~~~\n\n.. autoclass:: oandapyV20.types.OrderSpecifier\n    :members:\n    :undoc-members:\n    :inherited-members:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/types/PriceValue.rst",
    "content": "PriceValue\n~~~~~~~~~~\n\n.. autoclass:: oandapyV20.types.PriceValue\n    :members:\n    :undoc-members:\n    :inherited-members:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/types/TradeID.rst",
    "content": "TradeID\n~~~~~~~\n\n.. autoclass:: oandapyV20.types.TradeID\n    :members:\n    :undoc-members:\n    :inherited-members:\n    :special-members: __init__\n"
  },
  {
    "path": "docs/types/Units.rst",
    "content": "Units\n~~~~~\n\n.. autoclass:: oandapyV20.types.Units\n    :members:\n    :undoc-members:\n    :inherited-members:\n    :special-members: __init__\n"
  },
  {
    "path": "examples/README.rst",
    "content": "Examples\n========\n\nAs of Nov 28th 2016 examples are in a separate repo: oandapyV20-examples_\n\n.. _oandapyV20-examples: https://github.com/hootnot/oandapyV20-examples\n"
  },
  {
    "path": "jupyter/account.txt",
    "content": "xxx-yyy-zzzzzzz-aaa\n"
  },
  {
    "path": "jupyter/accounts.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"source\": [\n    \"[index](./index.ipynb) | [accounts](./accounts.ipynb) | [orders](./orders.ipynb) | [trades](./trades.ipynb) | [positions](./positions.ipynb) | [historical](./historical.ipynb) | [streams](./streams.ipynb) | [errors](./exceptions.ipynb)\\n\",\n    \"\\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"source\": [\n    \"## Account endpoints\\n\",\n    \"\\n\",\n    \"### Example: fetch account information\\n\",\n    \"\\n\",\n    \"A simple example to retrieve the accounts belonging to a *token*:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 1,\n   \"metadata\": {\n    \"collapsed\": false,\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"{\\n\",\n      \"  \\\"accounts\\\": [\\n\",\n      \"    {\\n\",\n      \"      \\\"tags\\\": [],\\n\",\n      \"      \\\"id\\\": \\\"101-004-1435156-002\\\"\\n\",\n      \"    },\\n\",\n      \"    {\\n\",\n      \"      \\\"tags\\\": [],\\n\",\n      \"      \\\"id\\\": \\\"101-004-1435156-001\\\"\\n\",\n      \"    }\\n\",\n      \"  ]\\n\",\n      \"}\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"import json\\n\",\n    \"import oandapyV20\\n\",\n    \"import oandapyV20.endpoints.accounts as accounts\\n\",\n    \"from exampleauth import exampleauth\\n\",\n    \"\\n\",\n    \"accountID, access_token = exampleauth.exampleAuth()\\n\",\n    \"client = oandapyV20.API(access_token=access_token)\\n\",\n    \"\\n\",\n    \"r = accounts.AccountList()\\n\",\n    \"response = client.request(r)\\n\",\n    \"print(json.dumps(response, indent=2))\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"source\": [\n    \"### Request details\\n\",\n    \"\\n\",\n    \"Lets get some details from the request itself after the client performed the request:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 2,\n   \"metadata\": {\n    \"collapsed\": false,\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"API-path:  v3/accounts\\n\",\n      \"METHOD:  GET\\n\",\n      \"Response status:  200\\n\",\n      \"The account id's:  ['101-004-1435156-002', '101-004-1435156-001']\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"print(\\\"API-path: \\\" , r)\\n\",\n    \"print(\\\"METHOD: \\\", r.method)\\n\",\n    \"print(\\\"Response status: \\\", r.status_code)\\n\",\n    \"print(\\\"The account id's: \\\", [acc.get('id') for acc in r.response.get('accounts')])\"\n   ]\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"Python 3\",\n   \"language\": \"python\",\n   \"name\": \"python3\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.5.2\"\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 2\n}\n"
  },
  {
    "path": "jupyter/exampleauth/__init__.py",
    "content": ""
  },
  {
    "path": "jupyter/exampleauth/exampleauth.py",
    "content": "\"\"\"simple auth method for examples.\"\"\"\n\n\ndef exampleAuth():\n    accountID, token = None, None\n    with open(\"account.txt\") as I:\n        accountID = I.read().strip()\n    with open(\"token.txt\") as I:\n        token = I.read().strip()\n    return accountID, token\n"
  },
  {
    "path": "jupyter/exceptions.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"source\": [\n    \"[index](./index.ipynb) | [accounts](./accounts.ipynb) | [orders](./orders.ipynb) | [trades](./trades.ipynb) | [positions](./positions.ipynb) | [historical](./historical.ipynb) | [streams](./streams.ipynb) | [errors](./exceptions.ipynb)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"source\": [\n    \"## What about errors ?\\n\",\n    \"\\n\",\n    \"Errors can occur. Wrong parameters or connection errors for example. Lets take the example from [Orders](./orders.ipynb) and make the instrument one that does not exist. The orderspecfication itself is still valid. Wrap it up in a *try/except* to catch the error:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 3,\n   \"metadata\": {\n    \"collapsed\": false,\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"V20Error occurred: {\\\"errorMessage\\\":\\\"Invalid value specified for 'order.instrument'\\\"}\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"import json\\n\",\n    \"import oandapyV20\\n\",\n    \"from oandapyV20.exceptions import V20Error\\n\",\n    \"import oandapyV20.endpoints.orders as orders\\n\",\n    \"from oandapyV20.contrib.requests import (\\n\",\n    \"    MarketOrderRequest,\\n\",\n    \"    TakeProfitDetails,\\n\",\n    \"    StopLossDetails)\\n\",\n    \"from exampleauth import exampleauth\\n\",\n    \"\\n\",\n    \"accountID, access_token = exampleauth.exampleAuth()\\n\",\n    \"client = oandapyV20.API(access_token=access_token)\\n\",\n    \"\\n\",\n    \"mktOrder = MarketOrderRequest(instrument=\\\"EUR_UDS\\\",    # EUR_UDS ... the faulty instrument\\n\",\n    \"                              units=10000,\\n\",\n    \"                              takeProfitOnFill=TakeProfitDetails(price=1.10).data,\\n\",\n    \"                              stopLossOnFill=StopLossDetails(price=1.05).data\\n\",\n    \"                              ).data\\n\",\n    \"r = orders.OrderCreate(accountID=accountID, data=mktOrder)\\n\",\n    \"try:\\n\",\n    \"    rv = client.request(r)\\n\",\n    \"except V20Error as err:\\n\",\n    \"    print(\\\"V20Error occurred: {}\\\".format(err))\\n\",\n    \"else:\\n\",\n    \"    print(\\\"Response: {}\\\\n{}\\\".format(r.status_code, json.dumps(rv, indent=2)))\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"source\": [\n    \"As we can see the REST-API returned an error response saying the instrument is invalid.\"\n   ]\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"Python 3\",\n   \"language\": \"python\",\n   \"name\": \"python3\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.5.2\"\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 2\n}\n"
  },
  {
    "path": "jupyter/historical.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"source\": [\n    \"[accounts](./accounts.ipynb) | [orders](./orders.ipynb) | [trades](./trades.ipynb) | [positions](./positions.ipynb) | [historical](./historical.ipynb) | [streams](./streams.ipynb) | [errors](./exceptions.ipynb)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"source\": [\n    \"# Historical data\\n\",\n    \"\\n\",\n    \"OANDA provides access to historical data. The *oandapyV20* has a class to access this data: *oandapyV20.endpoints.instruments.InstrumentsCandles*.\\n\",\n    \"\\n\",\n    \"Lets give it a try and download some data for:\\n\",\n    \"  + instrument: EUR_USD\\n\",\n    \"  + granularity: H1\\n\",\n    \"  + from: 2017-01-01T00:00:00\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 6,\n   \"metadata\": {\n    \"collapsed\": false,\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"Request: v3/instruments/EUR_USD/candles  #candles received: 9\\n\",\n      \"{\\n\",\n      \"  \\\"instrument\\\": \\\"EUR_USD\\\", \\n\",\n      \"  \\\"candles\\\": [\\n\",\n      \"    {\\n\",\n      \"      \\\"volume\\\": 481, \\n\",\n      \"      \\\"mid\\\": {\\n\",\n      \"        \\\"h\\\": \\\"1.04712\\\", \\n\",\n      \"        \\\"c\\\": \\\"1.04662\\\", \\n\",\n      \"        \\\"l\\\": \\\"1.04572\\\", \\n\",\n      \"        \\\"o\\\": \\\"1.04577\\\"\\n\",\n      \"      }, \\n\",\n      \"      \\\"complete\\\": true, \\n\",\n      \"      \\\"time\\\": \\\"2017-01-03T00:00:00.000000000Z\\\"\\n\",\n      \"    }, \\n\",\n      \"    {\\n\",\n      \"      \\\"volume\\\": 664, \\n\",\n      \"      \\\"mid\\\": {\\n\",\n      \"        \\\"h\\\": \\\"1.04808\\\", \\n\",\n      \"        \\\"c\\\": \\\"1.04758\\\", \\n\",\n      \"        \\\"l\\\": \\\"1.04646\\\", \\n\",\n      \"        \\\"o\\\": \\\"1.04665\\\"\\n\",\n      \"      }, \\n\",\n      \"      \\\"complete\\\": true, \\n\",\n      \"      \\\"time\\\": \\\"2017-01-03T01:00:00.000000000Z\\\"\\n\",\n      \"    }, \\n\",\n      \"    {\\n\",\n      \"      \\\"volume\\\": 392, \\n\",\n      \"      \\\"mid\\\": {\\n\",\n      \"        \\\"h\\\": \\\"1.04780\\\", \\n\",\n      \"        \\\"c\\\": \\\"1.04721\\\", \\n\",\n      \"        \\\"l\\\": \\\"1.04709\\\", \\n\",\n      \"        \\\"o\\\": \\\"1.04761\\\"\\n\",\n      \"      }, \\n\",\n      \"      \\\"complete\\\": true, \\n\",\n      \"      \\\"time\\\": \\\"2017-01-03T02:00:00.000000000Z\\\"\\n\",\n      \"    }, \\n\",\n      \"    {\\n\",\n      \"      \\\"volume\\\": 394, \\n\",\n      \"      \\\"mid\\\": {\\n\",\n      \"        \\\"h\\\": \\\"1.04848\\\", \\n\",\n      \"        \\\"c\\\": \\\"1.04848\\\", \\n\",\n      \"        \\\"l\\\": \\\"1.04715\\\", \\n\",\n      \"        \\\"o\\\": \\\"1.04718\\\"\\n\",\n      \"      }, \\n\",\n      \"      \\\"complete\\\": true, \\n\",\n      \"      \\\"time\\\": \\\"2017-01-03T03:00:00.000000000Z\\\"\\n\",\n      \"    }, \\n\",\n      \"    {\\n\",\n      \"      \\\"volume\\\": 285, \\n\",\n      \"      \\\"mid\\\": {\\n\",\n      \"        \\\"h\\\": \\\"1.04898\\\", \\n\",\n      \"        \\\"c\\\": \\\"1.04884\\\", \\n\",\n      \"        \\\"l\\\": \\\"1.04820\\\", \\n\",\n      \"        \\\"o\\\": \\\"1.04852\\\"\\n\",\n      \"      }, \\n\",\n      \"      \\\"complete\\\": true, \\n\",\n      \"      \\\"time\\\": \\\"2017-01-03T04:00:00.000000000Z\\\"\\n\",\n      \"    }, \\n\",\n      \"    {\\n\",\n      \"      \\\"volume\\\": 250, \\n\",\n      \"      \\\"mid\\\": {\\n\",\n      \"        \\\"h\\\": \\\"1.04902\\\", \\n\",\n      \"        \\\"c\\\": \\\"1.04824\\\", \\n\",\n      \"        \\\"l\\\": \\\"1.04816\\\", \\n\",\n      \"        \\\"o\\\": \\\"1.04886\\\"\\n\",\n      \"      }, \\n\",\n      \"      \\\"complete\\\": true, \\n\",\n      \"      \\\"time\\\": \\\"2017-01-03T05:00:00.000000000Z\\\"\\n\",\n      \"    }, \\n\",\n      \"    {\\n\",\n      \"      \\\"volume\\\": 368, \\n\",\n      \"      \\\"mid\\\": {\\n\",\n      \"        \\\"h\\\": \\\"1.04892\\\", \\n\",\n      \"        \\\"c\\\": \\\"1.04882\\\", \\n\",\n      \"        \\\"l\\\": \\\"1.04813\\\", \\n\",\n      \"        \\\"o\\\": \\\"1.04821\\\"\\n\",\n      \"      }, \\n\",\n      \"      \\\"complete\\\": true, \\n\",\n      \"      \\\"time\\\": \\\"2017-01-03T06:00:00.000000000Z\\\"\\n\",\n      \"    }, \\n\",\n      \"    {\\n\",\n      \"      \\\"volume\\\": 1639, \\n\",\n      \"      \\\"mid\\\": {\\n\",\n      \"        \\\"h\\\": \\\"1.04888\\\", \\n\",\n      \"        \\\"c\\\": \\\"1.04602\\\", \\n\",\n      \"        \\\"l\\\": \\\"1.04536\\\", \\n\",\n      \"        \\\"o\\\": \\\"1.04885\\\"\\n\",\n      \"      }, \\n\",\n      \"      \\\"complete\\\": true, \\n\",\n      \"      \\\"time\\\": \\\"2017-01-03T07:00:00.000000000Z\\\"\\n\",\n      \"    }, \\n\",\n      \"    {\\n\",\n      \"      \\\"volume\\\": 2830, \\n\",\n      \"      \\\"mid\\\": {\\n\",\n      \"        \\\"h\\\": \\\"1.04658\\\", \\n\",\n      \"        \\\"c\\\": \\\"1.04353\\\", \\n\",\n      \"        \\\"l\\\": \\\"1.04207\\\", \\n\",\n      \"        \\\"o\\\": \\\"1.04606\\\"\\n\",\n      \"      }, \\n\",\n      \"      \\\"complete\\\": true, \\n\",\n      \"      \\\"time\\\": \\\"2017-01-03T08:00:00.000000000Z\\\"\\n\",\n      \"    }\\n\",\n      \"  ], \\n\",\n      \"  \\\"granularity\\\": \\\"H1\\\"\\n\",\n      \"}\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"import json\\n\",\n    \"import oandapyV20\\n\",\n    \"import oandapyV20.endpoints.instruments as instruments\\n\",\n    \"from exampleauth import exampleauth\\n\",\n    \"\\n\",\n    \"accountID, access_token = exampleauth.exampleAuth()\\n\",\n    \"client = oandapyV20.API(access_token=access_token)\\n\",\n    \"\\n\",\n    \"instrument = \\\"EUR_USD\\\"\\n\",\n    \"params = {\\n\",\n    \"    \\\"from\\\": \\\"2017-01-01T00:00:00Z\\\",\\n\",\n    \"    \\\"granularity\\\": \\\"H1\\\",\\n\",\n    \"    \\\"count\\\": 10,\\n\",\n    \"}\\n\",\n    \"r = instruments.InstrumentsCandles(instrument=instrument, params=params)\\n\",\n    \"response = client.request(r)\\n\",\n    \"print(\\\"Request: {}  #candles received: {}\\\".format(r, len(r.response.get('candles'))))\\n\",\n    \"print(json.dumps(response, indent=2))\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"source\": [\n    \"So, that is 9 records?\\n\",\n    \"... that can be fixed by including the parameter *includeFirst*, see the OANDA documentation for details.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 8,\n   \"metadata\": {\n    \"collapsed\": false,\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"Request: v3/instruments/EUR_USD/candles  #candles received: 10\\n\",\n      \"{\\n\",\n      \"  \\\"instrument\\\": \\\"EUR_USD\\\", \\n\",\n      \"  \\\"candles\\\": [\\n\",\n      \"    {\\n\",\n      \"      \\\"volume\\\": 974, \\n\",\n      \"      \\\"mid\\\": {\\n\",\n      \"        \\\"h\\\": \\\"1.04711\\\", \\n\",\n      \"        \\\"c\\\": \\\"1.04575\\\", \\n\",\n      \"        \\\"l\\\": \\\"1.04567\\\", \\n\",\n      \"        \\\"o\\\": \\\"1.04684\\\"\\n\",\n      \"      }, \\n\",\n      \"      \\\"complete\\\": true, \\n\",\n      \"      \\\"time\\\": \\\"2017-01-02T23:00:00.000000000Z\\\"\\n\",\n      \"    }, \\n\",\n      \"    {\\n\",\n      \"      \\\"volume\\\": 481, \\n\",\n      \"      \\\"mid\\\": {\\n\",\n      \"        \\\"h\\\": \\\"1.04712\\\", \\n\",\n      \"        \\\"c\\\": \\\"1.04662\\\", \\n\",\n      \"        \\\"l\\\": \\\"1.04572\\\", \\n\",\n      \"        \\\"o\\\": \\\"1.04577\\\"\\n\",\n      \"      }, \\n\",\n      \"      \\\"complete\\\": true, \\n\",\n      \"      \\\"time\\\": \\\"2017-01-03T00:00:00.000000000Z\\\"\\n\",\n      \"    }, \\n\",\n      \"    {\\n\",\n      \"      \\\"volume\\\": 664, \\n\",\n      \"      \\\"mid\\\": {\\n\",\n      \"        \\\"h\\\": \\\"1.04808\\\", \\n\",\n      \"        \\\"c\\\": \\\"1.04758\\\", \\n\",\n      \"        \\\"l\\\": \\\"1.04646\\\", \\n\",\n      \"        \\\"o\\\": \\\"1.04665\\\"\\n\",\n      \"      }, \\n\",\n      \"      \\\"complete\\\": true, \\n\",\n      \"      \\\"time\\\": \\\"2017-01-03T01:00:00.000000000Z\\\"\\n\",\n      \"    }, \\n\",\n      \"    {\\n\",\n      \"      \\\"volume\\\": 392, \\n\",\n      \"      \\\"mid\\\": {\\n\",\n      \"        \\\"h\\\": \\\"1.04780\\\", \\n\",\n      \"        \\\"c\\\": \\\"1.04721\\\", \\n\",\n      \"        \\\"l\\\": \\\"1.04709\\\", \\n\",\n      \"        \\\"o\\\": \\\"1.04761\\\"\\n\",\n      \"      }, \\n\",\n      \"      \\\"complete\\\": true, \\n\",\n      \"      \\\"time\\\": \\\"2017-01-03T02:00:00.000000000Z\\\"\\n\",\n      \"    }, \\n\",\n      \"    {\\n\",\n      \"      \\\"volume\\\": 394, \\n\",\n      \"      \\\"mid\\\": {\\n\",\n      \"        \\\"h\\\": \\\"1.04848\\\", \\n\",\n      \"        \\\"c\\\": \\\"1.04848\\\", \\n\",\n      \"        \\\"l\\\": \\\"1.04715\\\", \\n\",\n      \"        \\\"o\\\": \\\"1.04718\\\"\\n\",\n      \"      }, \\n\",\n      \"      \\\"complete\\\": true, \\n\",\n      \"      \\\"time\\\": \\\"2017-01-03T03:00:00.000000000Z\\\"\\n\",\n      \"    }, \\n\",\n      \"    {\\n\",\n      \"      \\\"volume\\\": 285, \\n\",\n      \"      \\\"mid\\\": {\\n\",\n      \"        \\\"h\\\": \\\"1.04898\\\", \\n\",\n      \"        \\\"c\\\": \\\"1.04884\\\", \\n\",\n      \"        \\\"l\\\": \\\"1.04820\\\", \\n\",\n      \"        \\\"o\\\": \\\"1.04852\\\"\\n\",\n      \"      }, \\n\",\n      \"      \\\"complete\\\": true, \\n\",\n      \"      \\\"time\\\": \\\"2017-01-03T04:00:00.000000000Z\\\"\\n\",\n      \"    }, \\n\",\n      \"    {\\n\",\n      \"      \\\"volume\\\": 250, \\n\",\n      \"      \\\"mid\\\": {\\n\",\n      \"        \\\"h\\\": \\\"1.04902\\\", \\n\",\n      \"        \\\"c\\\": \\\"1.04824\\\", \\n\",\n      \"        \\\"l\\\": \\\"1.04816\\\", \\n\",\n      \"        \\\"o\\\": \\\"1.04886\\\"\\n\",\n      \"      }, \\n\",\n      \"      \\\"complete\\\": true, \\n\",\n      \"      \\\"time\\\": \\\"2017-01-03T05:00:00.000000000Z\\\"\\n\",\n      \"    }, \\n\",\n      \"    {\\n\",\n      \"      \\\"volume\\\": 368, \\n\",\n      \"      \\\"mid\\\": {\\n\",\n      \"        \\\"h\\\": \\\"1.04892\\\", \\n\",\n      \"        \\\"c\\\": \\\"1.04882\\\", \\n\",\n      \"        \\\"l\\\": \\\"1.04813\\\", \\n\",\n      \"        \\\"o\\\": \\\"1.04821\\\"\\n\",\n      \"      }, \\n\",\n      \"      \\\"complete\\\": true, \\n\",\n      \"      \\\"time\\\": \\\"2017-01-03T06:00:00.000000000Z\\\"\\n\",\n      \"    }, \\n\",\n      \"    {\\n\",\n      \"      \\\"volume\\\": 1639, \\n\",\n      \"      \\\"mid\\\": {\\n\",\n      \"        \\\"h\\\": \\\"1.04888\\\", \\n\",\n      \"        \\\"c\\\": \\\"1.04602\\\", \\n\",\n      \"        \\\"l\\\": \\\"1.04536\\\", \\n\",\n      \"        \\\"o\\\": \\\"1.04885\\\"\\n\",\n      \"      }, \\n\",\n      \"      \\\"complete\\\": true, \\n\",\n      \"      \\\"time\\\": \\\"2017-01-03T07:00:00.000000000Z\\\"\\n\",\n      \"    }, \\n\",\n      \"    {\\n\",\n      \"      \\\"volume\\\": 2830, \\n\",\n      \"      \\\"mid\\\": {\\n\",\n      \"        \\\"h\\\": \\\"1.04658\\\", \\n\",\n      \"        \\\"c\\\": \\\"1.04353\\\", \\n\",\n      \"        \\\"l\\\": \\\"1.04207\\\", \\n\",\n      \"        \\\"o\\\": \\\"1.04606\\\"\\n\",\n      \"      }, \\n\",\n      \"      \\\"complete\\\": true, \\n\",\n      \"      \\\"time\\\": \\\"2017-01-03T08:00:00.000000000Z\\\"\\n\",\n      \"    }\\n\",\n      \"  ], \\n\",\n      \"  \\\"granularity\\\": \\\"H1\\\"\\n\",\n      \"}\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"instrument = \\\"EUR_USD\\\"\\n\",\n    \"params = {\\n\",\n    \"    \\\"from\\\": \\\"2017-01-01T00:00:00Z\\\",\\n\",\n    \"    \\\"granularity\\\": \\\"H1\\\",\\n\",\n    \"    \\\"includeFirst\\\": True,\\n\",\n    \"    \\\"count\\\": 10,\\n\",\n    \"}\\n\",\n    \"r = instruments.InstrumentsCandles(instrument=instrument, params=params)\\n\",\n    \"response = client.request(r)\\n\",\n    \"print(\\\"Request: {}  #candles received: {}\\\".format(r, len(r.response.get('candles'))))\\n\",\n    \"print(json.dumps(response, indent=2))\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"source\": [\n    \"# Bulk history\\n\",\n    \"\\n\",\n    \"## InstrumentsCandles class\\n\",\n    \"\\n\",\n    \"It is likely that you want to retrieve more than 10 records. The OANDA docs say that the default number of records\\n\",\n    \"is 500, in case you do not specify. You can specify the number of records to retrieve by using *count*, with a maximum of 5000. The *InstrumentsCandles* class enables you to retrieve the records.\\n\",\n    \"\\n\",\n    \"## InstrumentsCandlesFactory\\n\",\n    \"\\n\",\n    \"Now if you would like to retrieve a lot of history, you have to make consecutive requests. To make this an easy process the *oandapyV20* library comes with a so called *factory* named *InstrumentsCandlesFactory*.\\n\",\n    \"\\n\",\n    \"Using this class you can retrieve all history of an instrument from a certain date. The *InstrumentsCandlesFactory* acts as a generator generating *InstrumentCandles* requests until all data is retrieved. The number of requests can be influenced by specifying *count*. Setting *count* to 5000 would generate a tenth of the requests vs. the default of 500.\\n\",\n    \"\\n\",\n    \"Back to our example: lets make sure we request a lot of data, so we set the *granularity* to *M5* and leave the date at 2017-01-01T00:00:00. The will retrieve all records from that date up to today, because we did not specify the *to* parameter. \\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 13,\n   \"metadata\": {\n    \"collapsed\": false,\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-01-02T17:40:00Z', 'from': '2017-01-01T00:00:00Z', 'granularity': 'M5'}, received: 0\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-01-04T11:25:00Z', 'from': '2017-01-02T17:45:00Z', 'granularity': 'M5'}, received: 436\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-01-06T05:10:00Z', 'from': '2017-01-04T11:30:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-01-07T22:55:00Z', 'from': '2017-01-06T05:15:00Z', 'granularity': 'M5'}, received: 200\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-01-09T16:40:00Z', 'from': '2017-01-07T23:00:00Z', 'granularity': 'M5'}, received: 222\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-01-11T10:25:00Z', 'from': '2017-01-09T16:45:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-01-13T04:10:00Z', 'from': '2017-01-11T10:30:00Z', 'granularity': 'M5'}, received: 498\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-01-14T21:55:00Z', 'from': '2017-01-13T04:15:00Z', 'granularity': 'M5'}, received: 212\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-01-16T15:40:00Z', 'from': '2017-01-14T22:00:00Z', 'granularity': 'M5'}, received: 211\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-01-18T09:25:00Z', 'from': '2017-01-16T15:45:00Z', 'granularity': 'M5'}, received: 497\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-01-20T03:10:00Z', 'from': '2017-01-18T09:30:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-01-21T20:55:00Z', 'from': '2017-01-20T03:15:00Z', 'granularity': 'M5'}, received: 224\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-01-23T14:40:00Z', 'from': '2017-01-21T21:00:00Z', 'granularity': 'M5'}, received: 193\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-01-25T08:25:00Z', 'from': '2017-01-23T14:45:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-01-27T02:10:00Z', 'from': '2017-01-25T08:30:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-01-28T19:55:00Z', 'from': '2017-01-27T02:15:00Z', 'granularity': 'M5'}, received: 236\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-01-30T13:40:00Z', 'from': '2017-01-28T20:00:00Z', 'granularity': 'M5'}, received: 187\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-02-01T07:25:00Z', 'from': '2017-01-30T13:45:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-02-03T01:10:00Z', 'from': '2017-02-01T07:30:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-02-04T18:55:00Z', 'from': '2017-02-03T01:15:00Z', 'granularity': 'M5'}, received: 248\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-02-06T12:40:00Z', 'from': '2017-02-04T19:00:00Z', 'granularity': 'M5'}, received: 175\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-02-08T06:25:00Z', 'from': '2017-02-06T12:45:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-02-10T00:10:00Z', 'from': '2017-02-08T06:30:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-02-11T17:55:00Z', 'from': '2017-02-10T00:15:00Z', 'granularity': 'M5'}, received: 260\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-02-13T11:40:00Z', 'from': '2017-02-11T18:00:00Z', 'granularity': 'M5'}, received: 163\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-02-15T05:25:00Z', 'from': '2017-02-13T11:45:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-02-16T23:10:00Z', 'from': '2017-02-15T05:30:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-02-18T16:55:00Z', 'from': '2017-02-16T23:15:00Z', 'granularity': 'M5'}, received: 272\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-02-20T10:40:00Z', 'from': '2017-02-18T17:00:00Z', 'granularity': 'M5'}, received: 151\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-02-22T04:25:00Z', 'from': '2017-02-20T10:45:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-02-23T22:10:00Z', 'from': '2017-02-22T04:30:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-02-25T15:55:00Z', 'from': '2017-02-23T22:15:00Z', 'granularity': 'M5'}, received: 284\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-02-27T09:40:00Z', 'from': '2017-02-25T16:00:00Z', 'granularity': 'M5'}, received: 139\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-03-01T03:25:00Z', 'from': '2017-02-27T09:45:00Z', 'granularity': 'M5'}, received: 498\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-03-02T21:10:00Z', 'from': '2017-03-01T03:30:00Z', 'granularity': 'M5'}, received: 498\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-03-04T14:55:00Z', 'from': '2017-03-02T21:15:00Z', 'granularity': 'M5'}, received: 296\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-03-06T08:40:00Z', 'from': '2017-03-04T15:00:00Z', 'granularity': 'M5'}, received: 127\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-03-08T02:25:00Z', 'from': '2017-03-06T08:45:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-03-09T20:10:00Z', 'from': '2017-03-08T02:30:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-03-11T13:55:00Z', 'from': '2017-03-09T20:15:00Z', 'granularity': 'M5'}, received: 308\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-03-13T07:40:00Z', 'from': '2017-03-11T14:00:00Z', 'granularity': 'M5'}, received: 126\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-03-15T01:25:00Z', 'from': '2017-03-13T07:45:00Z', 'granularity': 'M5'}, received: 497\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-03-16T19:10:00Z', 'from': '2017-03-15T01:30:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-03-18T12:55:00Z', 'from': '2017-03-16T19:15:00Z', 'granularity': 'M5'}, received: 308\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-03-20T06:40:00Z', 'from': '2017-03-18T13:00:00Z', 'granularity': 'M5'}, received: 115\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-03-22T00:25:00Z', 'from': '2017-03-20T06:45:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-03-23T18:10:00Z', 'from': '2017-03-22T00:30:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-03-25T11:55:00Z', 'from': '2017-03-23T18:15:00Z', 'granularity': 'M5'}, received: 319\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-03-27T05:40:00Z', 'from': '2017-03-25T12:00:00Z', 'granularity': 'M5'}, received: 103\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-03-28T23:25:00Z', 'from': '2017-03-27T05:45:00Z', 'granularity': 'M5'}, received: 497\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-03-30T17:10:00Z', 'from': '2017-03-28T23:30:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-04-01T10:55:00Z', 'from': '2017-03-30T17:15:00Z', 'granularity': 'M5'}, received: 331\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-04-03T04:40:00Z', 'from': '2017-04-01T11:00:00Z', 'granularity': 'M5'}, received: 91\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-04-04T22:25:00Z', 'from': '2017-04-03T04:45:00Z', 'granularity': 'M5'}, received: 497\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-04-06T16:10:00Z', 'from': '2017-04-04T22:30:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-04-08T09:55:00Z', 'from': '2017-04-06T16:15:00Z', 'granularity': 'M5'}, received: 343\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-04-10T03:40:00Z', 'from': '2017-04-08T10:00:00Z', 'granularity': 'M5'}, received: 79\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-04-11T21:25:00Z', 'from': '2017-04-10T03:45:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-04-13T15:10:00Z', 'from': '2017-04-11T21:30:00Z', 'granularity': 'M5'}, received: 497\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-04-15T08:55:00Z', 'from': '2017-04-13T15:15:00Z', 'granularity': 'M5'}, received: 352\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-04-17T02:40:00Z', 'from': '2017-04-15T09:00:00Z', 'granularity': 'M5'}, received: 67\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-04-18T20:25:00Z', 'from': '2017-04-17T02:45:00Z', 'granularity': 'M5'}, received: 496\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-04-20T14:10:00Z', 'from': '2017-04-18T20:30:00Z', 'granularity': 'M5'}, received: 497\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-04-22T07:55:00Z', 'from': '2017-04-20T14:15:00Z', 'granularity': 'M5'}, received: 366\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-04-24T01:40:00Z', 'from': '2017-04-22T08:00:00Z', 'granularity': 'M5'}, received: 55\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-04-25T19:25:00Z', 'from': '2017-04-24T01:45:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-04-27T13:10:00Z', 'from': '2017-04-25T19:30:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-04-29T06:55:00Z', 'from': '2017-04-27T13:15:00Z', 'granularity': 'M5'}, received: 379\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-05-01T00:40:00Z', 'from': '2017-04-29T07:00:00Z', 'granularity': 'M5'}, received: 43\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-05-02T18:25:00Z', 'from': '2017-05-01T00:45:00Z', 'granularity': 'M5'}, received: 497\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-05-04T12:10:00Z', 'from': '2017-05-02T18:30:00Z', 'granularity': 'M5'}, received: 496\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-05-06T05:55:00Z', 'from': '2017-05-04T12:15:00Z', 'granularity': 'M5'}, received: 392\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-05-07T23:40:00Z', 'from': '2017-05-06T06:00:00Z', 'granularity': 'M5'}, received: 31\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-05-09T17:25:00Z', 'from': '2017-05-07T23:45:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-05-11T11:10:00Z', 'from': '2017-05-09T17:30:00Z', 'granularity': 'M5'}, received: 498\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-05-13T04:55:00Z', 'from': '2017-05-11T11:15:00Z', 'granularity': 'M5'}, received: 402\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-05-14T22:40:00Z', 'from': '2017-05-13T05:00:00Z', 'granularity': 'M5'}, received: 19\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-05-16T16:25:00Z', 'from': '2017-05-14T22:45:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-05-18T10:10:00Z', 'from': '2017-05-16T16:30:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-05-20T03:55:00Z', 'from': '2017-05-18T10:15:00Z', 'granularity': 'M5'}, received: 416\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-05-21T21:40:00Z', 'from': '2017-05-20T04:00:00Z', 'granularity': 'M5'}, received: 7\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-05-23T15:25:00Z', 'from': '2017-05-21T21:45:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-05-25T09:10:00Z', 'from': '2017-05-23T15:30:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-05-27T02:55:00Z', 'from': '2017-05-25T09:15:00Z', 'granularity': 'M5'}, received: 428\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-05-28T20:40:00Z', 'from': '2017-05-27T03:00:00Z', 'granularity': 'M5'}, received: 0\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-05-30T14:25:00Z', 'from': '2017-05-28T20:45:00Z', 'granularity': 'M5'}, received: 491\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-06-01T08:10:00Z', 'from': '2017-05-30T14:30:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-06-03T01:55:00Z', 'from': '2017-06-01T08:15:00Z', 'granularity': 'M5'}, received: 440\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-06-04T19:40:00Z', 'from': '2017-06-03T02:00:00Z', 'granularity': 'M5'}, received: 0\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-06-06T13:25:00Z', 'from': '2017-06-04T19:45:00Z', 'granularity': 'M5'}, received: 483\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-06-08T07:10:00Z', 'from': '2017-06-06T13:30:00Z', 'granularity': 'M5'}, received: 498\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-06-10T00:55:00Z', 'from': '2017-06-08T07:15:00Z', 'granularity': 'M5'}, received: 452\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-06-11T18:40:00Z', 'from': '2017-06-10T01:00:00Z', 'granularity': 'M5'}, received: 0\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-06-13T12:25:00Z', 'from': '2017-06-11T18:45:00Z', 'granularity': 'M5'}, received: 471\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-06-15T06:10:00Z', 'from': '2017-06-13T12:30:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-06-16T23:55:00Z', 'from': '2017-06-15T06:15:00Z', 'granularity': 'M5'}, received: 464\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-06-18T17:40:00Z', 'from': '2017-06-17T00:00:00Z', 'granularity': 'M5'}, received: 0\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-06-20T11:25:00Z', 'from': '2017-06-18T17:45:00Z', 'granularity': 'M5'}, received: 458\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-06-22T05:10:00Z', 'from': '2017-06-20T11:30:00Z', 'granularity': 'M5'}, received: 495\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-06-23T22:55:00Z', 'from': '2017-06-22T05:15:00Z', 'granularity': 'M5'}, received: 474\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-06-25T16:40:00Z', 'from': '2017-06-23T23:00:00Z', 'granularity': 'M5'}, received: 0\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-06-27T10:25:00Z', 'from': '2017-06-25T16:45:00Z', 'granularity': 'M5'}, received: 444\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-06-29T04:10:00Z', 'from': '2017-06-27T10:30:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-06-30T21:55:00Z', 'from': '2017-06-29T04:15:00Z', 'granularity': 'M5'}, received: 488\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-07-02T15:40:00Z', 'from': '2017-06-30T22:00:00Z', 'granularity': 'M5'}, received: 0\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-07-04T09:25:00Z', 'from': '2017-07-02T15:45:00Z', 'granularity': 'M5'}, received: 433\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-07-06T03:10:00Z', 'from': '2017-07-04T09:30:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-07-07T20:55:00Z', 'from': '2017-07-06T03:15:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-07-09T14:40:00Z', 'from': '2017-07-07T21:00:00Z', 'granularity': 'M5'}, received: 0\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-07-11T08:25:00Z', 'from': '2017-07-09T14:45:00Z', 'granularity': 'M5'}, received: 422\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-07-13T02:10:00Z', 'from': '2017-07-11T08:30:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-07-14T19:55:00Z', 'from': '2017-07-13T02:15:00Z', 'granularity': 'M5'}, received: 498\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-07-16T13:40:00Z', 'from': '2017-07-14T20:00:00Z', 'granularity': 'M5'}, received: 11\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-07-18T07:25:00Z', 'from': '2017-07-16T13:45:00Z', 'granularity': 'M5'}, received: 412\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-07-20T01:10:00Z', 'from': '2017-07-18T07:30:00Z', 'granularity': 'M5'}, received: 498\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-07-21T18:55:00Z', 'from': '2017-07-20T01:15:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-07-23T12:40:00Z', 'from': '2017-07-21T19:00:00Z', 'granularity': 'M5'}, received: 23\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-07-25T06:25:00Z', 'from': '2017-07-23T12:45:00Z', 'granularity': 'M5'}, received: 400\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-07-27T00:10:00Z', 'from': '2017-07-25T06:30:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-07-28T17:55:00Z', 'from': '2017-07-27T00:15:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-07-30T11:40:00Z', 'from': '2017-07-28T18:00:00Z', 'granularity': 'M5'}, received: 35\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-08-01T05:25:00Z', 'from': '2017-07-30T11:45:00Z', 'granularity': 'M5'}, received: 388\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-08-02T23:10:00Z', 'from': '2017-08-01T05:30:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-08-04T16:55:00Z', 'from': '2017-08-02T23:15:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-08-06T10:40:00Z', 'from': '2017-08-04T17:00:00Z', 'granularity': 'M5'}, received: 47\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-08-08T04:25:00Z', 'from': '2017-08-06T10:45:00Z', 'granularity': 'M5'}, received: 376\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-08-09T22:10:00Z', 'from': '2017-08-08T04:30:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-08-11T15:55:00Z', 'from': '2017-08-09T22:15:00Z', 'granularity': 'M5'}, received: 498\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-08-13T09:40:00Z', 'from': '2017-08-11T16:00:00Z', 'granularity': 'M5'}, received: 59\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-08-15T03:25:00Z', 'from': '2017-08-13T09:45:00Z', 'granularity': 'M5'}, received: 364\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-08-16T21:10:00Z', 'from': '2017-08-15T03:30:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-08-18T14:55:00Z', 'from': '2017-08-16T21:15:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-08-20T08:40:00Z', 'from': '2017-08-18T15:00:00Z', 'granularity': 'M5'}, received: 71\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-08-22T02:25:00Z', 'from': '2017-08-20T08:45:00Z', 'granularity': 'M5'}, received: 352\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-08-23T20:10:00Z', 'from': '2017-08-22T02:30:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-08-25T13:55:00Z', 'from': '2017-08-23T20:15:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-08-27T07:40:00Z', 'from': '2017-08-25T14:00:00Z', 'granularity': 'M5'}, received: 83\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-08-29T01:25:00Z', 'from': '2017-08-27T07:45:00Z', 'granularity': 'M5'}, received: 340\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-08-30T19:10:00Z', 'from': '2017-08-29T01:30:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-09-01T12:55:00Z', 'from': '2017-08-30T19:15:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-09-03T06:40:00Z', 'from': '2017-09-01T13:00:00Z', 'granularity': 'M5'}, received: 95\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-09-05T00:25:00Z', 'from': '2017-09-03T06:45:00Z', 'granularity': 'M5'}, received: 325\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-09-06T18:10:00Z', 'from': '2017-09-05T00:30:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-09-08T11:55:00Z', 'from': '2017-09-06T18:15:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-09-10T05:40:00Z', 'from': '2017-09-08T12:00:00Z', 'granularity': 'M5'}, received: 107\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-09-11T23:25:00Z', 'from': '2017-09-10T05:45:00Z', 'granularity': 'M5'}, received: 315\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-09-13T17:10:00Z', 'from': '2017-09-11T23:30:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-09-15T10:55:00Z', 'from': '2017-09-13T17:15:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-09-17T04:40:00Z', 'from': '2017-09-15T11:00:00Z', 'granularity': 'M5'}, received: 119\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-09-18T22:25:00Z', 'from': '2017-09-17T04:45:00Z', 'granularity': 'M5'}, received: 303\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-09-20T16:10:00Z', 'from': '2017-09-18T22:30:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-09-22T09:55:00Z', 'from': '2017-09-20T16:15:00Z', 'granularity': 'M5'}, received: 499\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-09-24T03:40:00Z', 'from': '2017-09-22T10:00:00Z', 'granularity': 'M5'}, received: 131\\n\",\n      \"REQUEST: v3/instruments/EUR_USD/candles InstrumentsCandles {'to': '2017-09-24T17:54:30Z', 'from': '2017-09-24T03:45:00Z', 'granularity': 'M5'}, received: 0\\n\",\n      \"Check the datafile: /tmp/EUR_USD.M5.out under /tmp!, it contains 54090 records\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"import json\\n\",\n    \"import oandapyV20\\n\",\n    \"import oandapyV20.endpoints.instruments as instruments\\n\",\n    \"from oandapyV20.contrib.factories import InstrumentsCandlesFactory\\n\",\n    \"from exampleauth import exampleauth\\n\",\n    \"\\n\",\n    \"accountID, access_token = exampleauth.exampleAuth()\\n\",\n    \"client = oandapyV20.API(access_token=access_token)\\n\",\n    \"\\n\",\n    \"instrument = \\\"EUR_USD\\\"\\n\",\n    \"params = {\\n\",\n    \"    \\\"from\\\": \\\"2017-01-01T00:00:00Z\\\",\\n\",\n    \"    \\\"granularity\\\": \\\"M5\\\",\\n\",\n    \"}\\n\",\n    \"\\n\",\n    \"def cnv(r, h):\\n\",\n    \"    # get all candles from the response and write them as a record to the filehandle h\\n\",\n    \"    for candle in r.get('candles'):\\n\",\n    \"        ctime = candle.get('time')[0:19]\\n\",\n    \"        try:\\n\",\n    \"            rec = \\\"{time},{complete},{o},{h},{l},{c},{v}\\\".format(\\n\",\n    \"                time=ctime,\\n\",\n    \"                complete=candle['complete'],\\n\",\n    \"                o=candle['mid']['o'],\\n\",\n    \"                h=candle['mid']['h'],\\n\",\n    \"                l=candle['mid']['l'],\\n\",\n    \"                c=candle['mid']['c'],\\n\",\n    \"                v=candle['volume'],\\n\",\n    \"            )\\n\",\n    \"        except Exception as e:\\n\",\n    \"            print(e, r)\\n\",\n    \"        else:\\n\",\n    \"            h.write(rec+\\\"\\\\n\\\")\\n\",\n    \"\\n\",\n    \"datafile = \\\"/tmp/{}.{}.out\\\".format(instrument, params['granularity'])\\n\",\n    \"with open(datafile, \\\"w\\\") as O:\\n\",\n    \"    n = 0\\n\",\n    \"    for r in InstrumentsCandlesFactory(instrument=instrument, params=params):\\n\",\n    \"        rv = client.request(r)\\n\",\n    \"        cnt = len(r.response.get('candles'))\\n\",\n    \"        print(\\\"REQUEST: {} {} {}, received: {}\\\".format(r, r.__class__.__name__, r.params, cnt))\\n\",\n    \"        n += cnt\\n\",\n    \"        cnv(r.response, O)\\n\",\n    \"    print(\\\"Check the datafile: {} under /tmp!, it contains {} records\\\".format(datafile, n))\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"source\": [\n    \"## ... that was easy ...\\n\",\n    \"\\n\",\n    \"All request were made on the default of max. 500 records per request. With a granularity of *M5* this means that we have 288 records per day. The algorithm of the factory does not check on weekends or holidays. Therefore some request only return a part of the 500 requested records because there simply are no more records within the specified timespan.\\n\",\n    \"\\n\",\n    \"If you want to decrease the number of requests and increase the number of records returned for a request, just specify *count* as a number higher than 500 and up to max. 5000.\"\n   ]\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"Python 3\",\n   \"language\": \"python\",\n   \"name\": \"python3\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.5.2\"\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 2\n}\n"
  },
  {
    "path": "jupyter/index.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"source\": [\n    \"[accounts](./accounts.ipynb) | [orders](./orders.ipynb) | [trades](./trades.ipynb) | [positions](./positions.ipynb) | [historical](./historical.ipynb) | [streams](./streams.ipynb) | [errors](./exceptions.ipynb)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"source\": [\n    \"#  Tutorial oandapyV20\\n\",\n    \"\\n\",\n    \"## Installing *oandapyV20*\\n\",\n    \"\\n\",\n    \"Installing oandapyV20 from pypi:\\n\",\n    \"\\n\",\n    \"```shell\\n\",\n    \"$ pip install oandapyV20\\n\",\n    \"```\\n\",\n    \"\\n\",\n    \"## Tests\\n\",\n    \"\\n\",\n    \"If you want to run the tests, clone the repository:\\n\",\n    \"\\n\",\n    \"```bash\\n\",\n    \"\\n\",\n    \"    $ git clone https://github.com/hootnot/oanda-api-v20\\n\",\n    \"    $ cd oanda-api-v20\\n\",\n    \"\\n\",\n    \"    # install necessary packages for testing\\n\",\n    \"    $ grep \\\"\\\\- pip install\\\" .travis.yml |\\n\",\n    \"    > while read LNE\\n\",\n    \"    > do `echo $LNE| cut -c2-` ; done\\n\",\n    \"\\n\",\n    \"    $ python setup.py test\\n\",\n    \"    $ python setup.py install\\n\",\n    \"```\\n\",\n    \"\\n\",\n    \"## Jupyter\\n\",\n    \"\\n\",\n    \"To use this *Jupyter notebook* you need to install *Jupyter*:\\n\",\n    \"\\n\",\n    \"```shell\\n\",\n    \"$ pip install jupyter\\n\",\n    \"```\\n\",\n    \"\\n\",\n    \"See, [http://jupyter.org/install.html]() for all details regarding Jupyter.\\n\",\n    \"\\n\",\n    \"When installed you can start Jupyter from the cloned repo directory:\\n\",\n    \"\\n\",\n    \"```shell\\n\",\n    \"$ cd jupyter\\n\",\n    \"# provide your V20-accountID and token by editing account.txt and token.txt\\n\",\n    \"$ jupyter notebook\\n\",\n    \"# ... will launch your brouwser with the notebook tree structure.\\n\",\n    \"```\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"## Examples\\n\",\n    \"\\n\",\n    \"Examples are provided in the https://github.com/hootnot/oandapyV20-examples repository.\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"## Design\\n\",\n    \"\\n\",\n    \"The design of the oandapyV20 library differs from the library covering the REST-V1 interface:\\n\",\n    \"https://github.com/oanda/oandapy (oandapy), which is based on 'mixin' classes.\\n\",\n    \"\\n\",\n    \"### Client\\n\",\n    \"\\n\",\n    \"The V20-library has a client class (API) which processes all APIRequest objects. Status\\n\",\n    \"and response are properties of the request and are assigned by the client when performing \\n\",\n    \"the request. The response is also returned by the client. \\n\",\n    \"\\n\",\n    \"### Requests\\n\",\n    \"\\n\",\n    \"In the V20-library endpoints are represented as APIRequest objects derived from the\\n\",\n    \"APIRequest base class. Each endpoint group (accounts, trades, etc.) is represented\\n\",\n    \"by it's own (abstract) class covering the functionality of all endpoints for that group.\\n\",\n    \"Each endpoint within that group is covered by a class derived from the abstract class.\\n\",\n    \"\\n\",\n    \"## oandapyV20 step by step\\n\",\n    \"\\n\",\n    \"* [accounts](./accounts.ipynb)\\n\",\n    \"* [orders](./orders.ipynb)\\n\",\n    \"* [trades](./trades.ipynb)\\n\",\n    \"* [positions](./positions.ipynb)\\n\",\n    \"* [streams](./streams.ipynb)\\n\",\n    \"* [errors](./exceptions.ipynb)\\n\",\n    \"\\n\"\n   ]\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"Python 3\",\n   \"language\": \"python\",\n   \"name\": \"python3\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.5.2\"\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 2\n}\n"
  },
  {
    "path": "jupyter/orders.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"source\": [\n    \"[index](./index.ipynb) | [accounts](./accounts.ipynb) | [orders](./orders.ipynb) | [trades](./trades.ipynb) | [positions](./positions.ipynb) | [historical](./historical.ipynb) | [streams](./streams.ipynb) | [errors](./exceptions.ipynb)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"source\": [\n    \"## Orders\\n\",\n    \"\\n\",\n    \"This notebook provides an example of\\n\",\n    \"\\n\",\n    \"  + a MarketOrder\\n\",\n    \"  + a simplyfied way for a MarketOrder by using contrib.requests.MarketOrderRequest\\n\",\n    \"  + a LimitOrder with an expiry datetime by using *GTD* and contrib.requests.LimitOrderRequest\\n\",\n    \"  + canceling a GTD order\\n\",\n    \"\\n\",\n    \"### create a marketorder request with a TakeProfit and a StopLoss order when it gets filled.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 9,\n   \"metadata\": {\n    \"collapsed\": false,\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"Request:  v3/accounts/101-004-1435156-001/orders\\n\",\n      \"MarketOrder specs:  {\\n\",\n      \"  \\\"order\\\": {\\n\",\n      \"    \\\"timeInForce\\\": \\\"FOK\\\",\\n\",\n      \"    \\\"instrument\\\": \\\"EUR_USD\\\",\\n\",\n      \"    \\\"stopLossOnFill\\\": {\\n\",\n      \"      \\\"timeInForce\\\": \\\"GTC\\\",\\n\",\n      \"      \\\"price\\\": \\\"1.07\\\"\\n\",\n      \"    },\\n\",\n      \"    \\\"positionFill\\\": \\\"DEFAULT\\\",\\n\",\n      \"    \\\"units\\\": 10000,\\n\",\n      \"    \\\"takeProfitOnFill\\\": {\\n\",\n      \"      \\\"timeInForce\\\": \\\"GTC\\\",\\n\",\n      \"      \\\"price\\\": 1.1\\n\",\n      \"    },\\n\",\n      \"    \\\"type\\\": \\\"MARKET\\\"\\n\",\n      \"  }\\n\",\n      \"}\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"import json\\n\",\n    \"import oandapyV20\\n\",\n    \"import oandapyV20.endpoints.orders as orders\\n\",\n    \"from exampleauth import exampleauth\\n\",\n    \"\\n\",\n    \"accountID, access_token = exampleauth.exampleAuth()\\n\",\n    \"client = oandapyV20.API(access_token=access_token)\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"# create a market order to enter a LONG position 10000 EUR_USD, stopLoss @1.07 takeProfit @1.10 ( current: 1.055)\\n\",\n    \"# according to the docs at developer.oanda.com the requestbody looks like:\\n\",\n    \"\\n\",\n    \"mktOrder = {\\n\",\n    \"  \\\"order\\\": {\\n\",\n    \"    \\\"timeInForce\\\": \\\"FOK\\\",      # Fill-or-kill\\n\",\n    \"    \\\"instrument\\\": \\\"EUR_USD\\\",\\n\",\n    \"    \\\"positionFill\\\": \\\"DEFAULT\\\",\\n\",\n    \"    \\\"type\\\": \\\"MARKET\\\",\\n\",\n    \"    \\\"units\\\": 10000,            # as integer\\n\",\n    \"    \\\"takeProfitOnFill\\\": {\\n\",\n    \"      \\\"timeInForce\\\": \\\"GTC\\\",    # Good-till-cancelled\\n\",\n    \"      \\\"price\\\": 1.10            # as float\\n\",\n    \"    },\\n\",\n    \"    \\\"stopLossOnFill\\\": {\\n\",\n    \"      \\\"timeInForce\\\": \\\"GTC\\\",\\n\",\n    \"      \\\"price\\\": \\\"1.07\\\"          # as string\\n\",\n    \"    }\\n\",\n    \"  }\\n\",\n    \"}\\n\",\n    \"r = orders.OrderCreate(accountID=accountID, data=mktOrder)\\n\",\n    \"\\n\",\n    \"print(\\\"Request: \\\", r)\\n\",\n    \"print(\\\"MarketOrder specs: \\\", json.dumps(mktOrder, indent=2))\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"source\": [\n    \"Well that looks fine, but constructing orderbodies that way is not really what we want. Types are not checked for instance and all the defaults need to be supplied.\\n\",\n    \"\\n\",\n    \"This kind of datastructures can become complex, are not easy to read or construct and are prone to errors.\\n\",\n    \"\\n\",\n    \"## Types and definitions\\n\",\n    \"\\n\",\n    \"Oanda uses several *types* and *definitions* througout their documentation. These types are covered by the *oandapyV20.types* package and the definitions by the *oandapyV20.definitions* package.\\n\",\n    \"\\n\",\n    \"## Contrib.requests\\n\",\n    \"\\n\",\n    \"The *oandapyV20.contrib.requests* package offers classes providing an easy way to construct the data for\\n\",\n    \"the *data* parameter of the *OrderCreate* endpoint or the *TradeCRCDO* (Create/Replace/Cancel Dependent Orders). The *oandapyV20.contrib.requests* package makes use of the *oandapyV20.types* and *oandapyV20.definitions*.\\n\",\n    \"\\n\",\n    \"Let's improve the previous example by making use of *oandapyV20.contrib.requests*:\\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 1,\n   \"metadata\": {\n    \"collapsed\": false,\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"Request:  v3/accounts/101-004-1435156-001/orders\\n\",\n      \"MarketOrder specs:  {\\n\",\n      \"  \\\"order\\\": {\\n\",\n      \"    \\\"timeInForce\\\": \\\"FOK\\\",\\n\",\n      \"    \\\"instrument\\\": \\\"EUR_USD\\\",\\n\",\n      \"    \\\"positionFill\\\": \\\"DEFAULT\\\",\\n\",\n      \"    \\\"type\\\": \\\"MARKET\\\",\\n\",\n      \"    \\\"units\\\": \\\"10000\\\",\\n\",\n      \"    \\\"takeProfitOnFill\\\": {\\n\",\n      \"      \\\"timeInForce\\\": \\\"GTC\\\",\\n\",\n      \"      \\\"price\\\": \\\"1.10000\\\"\\n\",\n      \"    },\\n\",\n      \"    \\\"stopLossOnFill\\\": {\\n\",\n      \"      \\\"timeInForce\\\": \\\"GTC\\\",\\n\",\n      \"      \\\"price\\\": \\\"1.07000\\\"\\n\",\n      \"    }\\n\",\n      \"  }\\n\",\n      \"}\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"import json\\n\",\n    \"import oandapyV20\\n\",\n    \"import oandapyV20.endpoints.orders as orders\\n\",\n    \"from oandapyV20.contrib.requests import (\\n\",\n    \"    MarketOrderRequest,\\n\",\n    \"    TakeProfitDetails,\\n\",\n    \"    StopLossDetails)\\n\",\n    \"from exampleauth import exampleauth\\n\",\n    \"\\n\",\n    \"accountID, access_token = exampleauth.exampleAuth()\\n\",\n    \"client = oandapyV20.API(access_token=access_token)\\n\",\n    \"\\n\",\n    \"# create a market order to enter a LONG position 10000 EUR_USD\\n\",\n    \"mktOrder = MarketOrderRequest(instrument=\\\"EUR_USD\\\",\\n\",\n    \"                              units=10000,\\n\",\n    \"                              takeProfitOnFill=TakeProfitDetails(price=1.10).data,\\n\",\n    \"                              stopLossOnFill=StopLossDetails(price=1.07).data\\n\",\n    \"                              ).data\\n\",\n    \"r = orders.OrderCreate(accountID=accountID, data=mktOrder)\\n\",\n    \"\\n\",\n    \"print(\\\"Request: \\\", r)\\n\",\n    \"print(\\\"MarketOrder specs: \\\", json.dumps(mktOrder, indent=2))\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"source\": [\n    \"As you can see, the specs contain price values that were converted to strings and the defaults *positionFill* and *timeInForce* were added. Using *contrib.requests* makes it very easy to construct the orderdata body for order requests. Parameters for those requests are also validated.\\n\",\n    \"\\n\",\n    \"Next step, place the order:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 2,\n   \"metadata\": {\n    \"collapsed\": false,\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"Response: 201\\n\",\n      \"{\\n\",\n      \"  \\\"orderCancelTransaction\\\": {\\n\",\n      \"    \\\"time\\\": \\\"2017-03-09T13:17:59.319422181Z\\\",\\n\",\n      \"    \\\"userID\\\": 1435156,\\n\",\n      \"    \\\"batchID\\\": \\\"7576\\\",\\n\",\n      \"    \\\"orderID\\\": \\\"7576\\\",\\n\",\n      \"    \\\"id\\\": \\\"7577\\\",\\n\",\n      \"    \\\"type\\\": \\\"ORDER_CANCEL\\\",\\n\",\n      \"    \\\"accountID\\\": \\\"101-004-1435156-001\\\",\\n\",\n      \"    \\\"reason\\\": \\\"STOP_LOSS_ON_FILL_LOSS\\\"\\n\",\n      \"  },\\n\",\n      \"  \\\"lastTransactionID\\\": \\\"7577\\\",\\n\",\n      \"  \\\"orderCreateTransaction\\\": {\\n\",\n      \"    \\\"timeInForce\\\": \\\"FOK\\\",\\n\",\n      \"    \\\"instrument\\\": \\\"EUR_USD\\\",\\n\",\n      \"    \\\"batchID\\\": \\\"7576\\\",\\n\",\n      \"    \\\"accountID\\\": \\\"101-004-1435156-001\\\",\\n\",\n      \"    \\\"units\\\": \\\"10000\\\",\\n\",\n      \"    \\\"takeProfitOnFill\\\": {\\n\",\n      \"      \\\"timeInForce\\\": \\\"GTC\\\",\\n\",\n      \"      \\\"price\\\": \\\"1.10000\\\"\\n\",\n      \"    },\\n\",\n      \"    \\\"time\\\": \\\"2017-03-09T13:17:59.319422181Z\\\",\\n\",\n      \"    \\\"userID\\\": 1435156,\\n\",\n      \"    \\\"positionFill\\\": \\\"DEFAULT\\\",\\n\",\n      \"    \\\"id\\\": \\\"7576\\\",\\n\",\n      \"    \\\"type\\\": \\\"MARKET_ORDER\\\",\\n\",\n      \"    \\\"stopLossOnFill\\\": {\\n\",\n      \"      \\\"timeInForce\\\": \\\"GTC\\\",\\n\",\n      \"      \\\"price\\\": \\\"1.07000\\\"\\n\",\n      \"    },\\n\",\n      \"    \\\"reason\\\": \\\"CLIENT_ORDER\\\"\\n\",\n      \"  },\\n\",\n      \"  \\\"relatedTransactionIDs\\\": [\\n\",\n      \"    \\\"7576\\\",\\n\",\n      \"    \\\"7577\\\"\\n\",\n      \"  ]\\n\",\n      \"}\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"rv = client.request(r)\\n\",\n    \"print(\\\"Response: {}\\\\n{}\\\".format(r.status_code, json.dumps(rv, indent=2)))\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"source\": [\n    \"Lets analyze that. We see an *orderCancelTransaction* and *reason*  **STOP_LOSS_ON_FILL_LOSS**. So the order was not placed ? Well it was placed and cancelled right away. The marketprice of EUR_USD is at the moment of this writing 1.058. So the stopLoss order at 1.07 makes no sense. The status_code of 201 is as the specs say: http://developer.oanda.com/rest-live-v20/order-ep/ .\\n\",\n    \"\\n\",\n    \"Lets change the stopLoss level below the current price and place the order once again.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 3,\n   \"metadata\": {\n    \"collapsed\": false,\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"Response: 201\\n\",\n      \"{\\n\",\n      \"  \\\"orderFillTransaction\\\": {\\n\",\n      \"    \\\"accountBalance\\\": \\\"102107.4442\\\",\\n\",\n      \"    \\\"instrument\\\": \\\"EUR_USD\\\",\\n\",\n      \"    \\\"batchID\\\": \\\"7578\\\",\\n\",\n      \"    \\\"pl\\\": \\\"0.0000\\\",\\n\",\n      \"    \\\"accountID\\\": \\\"101-004-1435156-001\\\",\\n\",\n      \"    \\\"units\\\": \\\"10000\\\",\\n\",\n      \"    \\\"tradeOpened\\\": {\\n\",\n      \"      \\\"tradeID\\\": \\\"7579\\\",\\n\",\n      \"      \\\"units\\\": \\\"10000\\\"\\n\",\n      \"    },\\n\",\n      \"    \\\"financing\\\": \\\"0.0000\\\",\\n\",\n      \"    \\\"price\\\": \\\"1.05563\\\",\\n\",\n      \"    \\\"userID\\\": 1435156,\\n\",\n      \"    \\\"orderID\\\": \\\"7578\\\",\\n\",\n      \"    \\\"time\\\": \\\"2017-03-09T13:22:13.832587780Z\\\",\\n\",\n      \"    \\\"id\\\": \\\"7579\\\",\\n\",\n      \"    \\\"type\\\": \\\"ORDER_FILL\\\",\\n\",\n      \"    \\\"reason\\\": \\\"MARKET_ORDER\\\"\\n\",\n      \"  },\\n\",\n      \"  \\\"lastTransactionID\\\": \\\"7581\\\",\\n\",\n      \"  \\\"orderCreateTransaction\\\": {\\n\",\n      \"    \\\"timeInForce\\\": \\\"FOK\\\",\\n\",\n      \"    \\\"instrument\\\": \\\"EUR_USD\\\",\\n\",\n      \"    \\\"batchID\\\": \\\"7578\\\",\\n\",\n      \"    \\\"accountID\\\": \\\"101-004-1435156-001\\\",\\n\",\n      \"    \\\"units\\\": \\\"10000\\\",\\n\",\n      \"    \\\"takeProfitOnFill\\\": {\\n\",\n      \"      \\\"timeInForce\\\": \\\"GTC\\\",\\n\",\n      \"      \\\"price\\\": \\\"1.10000\\\"\\n\",\n      \"    },\\n\",\n      \"    \\\"time\\\": \\\"2017-03-09T13:22:13.832587780Z\\\",\\n\",\n      \"    \\\"userID\\\": 1435156,\\n\",\n      \"    \\\"positionFill\\\": \\\"DEFAULT\\\",\\n\",\n      \"    \\\"id\\\": \\\"7578\\\",\\n\",\n      \"    \\\"type\\\": \\\"MARKET_ORDER\\\",\\n\",\n      \"    \\\"stopLossOnFill\\\": {\\n\",\n      \"      \\\"timeInForce\\\": \\\"GTC\\\",\\n\",\n      \"      \\\"price\\\": \\\"1.05000\\\"\\n\",\n      \"    },\\n\",\n      \"    \\\"reason\\\": \\\"CLIENT_ORDER\\\"\\n\",\n      \"  },\\n\",\n      \"  \\\"relatedTransactionIDs\\\": [\\n\",\n      \"    \\\"7578\\\",\\n\",\n      \"    \\\"7579\\\",\\n\",\n      \"    \\\"7580\\\",\\n\",\n      \"    \\\"7581\\\"\\n\",\n      \"  ]\\n\",\n      \"}\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"mktOrder = MarketOrderRequest(instrument=\\\"EUR_USD\\\",\\n\",\n    \"                              units=10000,\\n\",\n    \"                              takeProfitOnFill=TakeProfitDetails(price=1.10).data,\\n\",\n    \"                              stopLossOnFill=StopLossDetails(price=1.05).data\\n\",\n    \"                              ).data\\n\",\n    \"r = orders.OrderCreate(accountID=accountID, data=mktOrder)\\n\",\n    \"rv = client.request(r)\\n\",\n    \"\\n\",\n    \"print(\\\"Response: {}\\\\n{}\\\".format(r.status_code, json.dumps(rv, indent=2)))\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"source\": [\n    \"We now see an *orderFillTransaction* for 10000 units EUR_USD with *reason* **MARKET_ORDER**.\\n\",\n    \"\\n\",\n    \"Lets retrieve the orders. We should see the *stopLoss* and *takeProfit* orders as *pending*:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 4,\n   \"metadata\": {\n    \"collapsed\": false,\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"Response:\\n\",\n      \" {\\n\",\n      \"  \\\"lastTransactionID\\\": \\\"7581\\\",\\n\",\n      \"  \\\"orders\\\": [\\n\",\n      \"    {\\n\",\n      \"      \\\"createTime\\\": \\\"2017-03-09T13:22:13.832587780Z\\\",\\n\",\n      \"      \\\"triggerCondition\\\": \\\"TRIGGER_DEFAULT\\\",\\n\",\n      \"      \\\"timeInForce\\\": \\\"GTC\\\",\\n\",\n      \"      \\\"price\\\": \\\"1.05000\\\",\\n\",\n      \"      \\\"tradeID\\\": \\\"7579\\\",\\n\",\n      \"      \\\"id\\\": \\\"7581\\\",\\n\",\n      \"      \\\"state\\\": \\\"PENDING\\\",\\n\",\n      \"      \\\"type\\\": \\\"STOP_LOSS\\\"\\n\",\n      \"    },\\n\",\n      \"    {\\n\",\n      \"      \\\"createTime\\\": \\\"2017-03-09T13:22:13.832587780Z\\\",\\n\",\n      \"      \\\"triggerCondition\\\": \\\"TRIGGER_DEFAULT\\\",\\n\",\n      \"      \\\"timeInForce\\\": \\\"GTC\\\",\\n\",\n      \"      \\\"price\\\": \\\"1.10000\\\",\\n\",\n      \"      \\\"tradeID\\\": \\\"7579\\\",\\n\",\n      \"      \\\"id\\\": \\\"7580\\\",\\n\",\n      \"      \\\"state\\\": \\\"PENDING\\\",\\n\",\n      \"      \\\"type\\\": \\\"TAKE_PROFIT\\\"\\n\",\n      \"    },\\n\",\n      \"    {\\n\",\n      \"      \\\"createTime\\\": \\\"2017-03-09T11:45:48.928448770Z\\\",\\n\",\n      \"      \\\"triggerCondition\\\": \\\"TRIGGER_DEFAULT\\\",\\n\",\n      \"      \\\"timeInForce\\\": \\\"GTC\\\",\\n\",\n      \"      \\\"price\\\": \\\"1.05000\\\",\\n\",\n      \"      \\\"tradeID\\\": \\\"7572\\\",\\n\",\n      \"      \\\"id\\\": \\\"7574\\\",\\n\",\n      \"      \\\"state\\\": \\\"PENDING\\\",\\n\",\n      \"      \\\"type\\\": \\\"STOP_LOSS\\\"\\n\",\n      \"    },\\n\",\n      \"    {\\n\",\n      \"      \\\"createTime\\\": \\\"2017-03-07T09:18:51.563637768Z\\\",\\n\",\n      \"      \\\"triggerCondition\\\": \\\"TRIGGER_DEFAULT\\\",\\n\",\n      \"      \\\"timeInForce\\\": \\\"GTC\\\",\\n\",\n      \"      \\\"price\\\": \\\"1.05000\\\",\\n\",\n      \"      \\\"tradeID\\\": \\\"7562\\\",\\n\",\n      \"      \\\"id\\\": \\\"7564\\\",\\n\",\n      \"      \\\"state\\\": \\\"PENDING\\\",\\n\",\n      \"      \\\"type\\\": \\\"STOP_LOSS\\\"\\n\",\n      \"    },\\n\",\n      \"    {\\n\",\n      \"      \\\"createTime\\\": \\\"2017-03-07T09:08:04.219010730Z\\\",\\n\",\n      \"      \\\"triggerCondition\\\": \\\"TRIGGER_DEFAULT\\\",\\n\",\n      \"      \\\"timeInForce\\\": \\\"GTC\\\",\\n\",\n      \"      \\\"price\\\": \\\"1.05000\\\",\\n\",\n      \"      \\\"tradeID\\\": \\\"7558\\\",\\n\",\n      \"      \\\"id\\\": \\\"7560\\\",\\n\",\n      \"      \\\"state\\\": \\\"PENDING\\\",\\n\",\n      \"      \\\"type\\\": \\\"STOP_LOSS\\\"\\n\",\n      \"    }\\n\",\n      \"  ]\\n\",\n      \"}\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"r = orders.OrdersPending(accountID=accountID)\\n\",\n    \"rv = client.request(r)\\n\",\n    \"print(\\\"Response:\\\\n\\\", json.dumps(rv, indent=2))\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"source\": [\n    \"Depending on the state of your account you should see at least the orders associated with the previously executed marketorder. The *relatedTransactionIDs* should be in the *orders* output of OrdersPending().\\n\",\n    \"\\n\",\n    \"Now lets cancel all pending TAKE_PROFIT orders:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 5,\n   \"metadata\": {\n    \"collapsed\": false,\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"Request: v3/accounts/101-004-1435156-001/orders/7580/cancel ... response: {\\n\",\n      \"  \\\"orderCancelTransaction\\\": {\\n\",\n      \"    \\\"time\\\": \\\"2017-03-09T13:26:07.480994423Z\\\",\\n\",\n      \"    \\\"userID\\\": 1435156,\\n\",\n      \"    \\\"batchID\\\": \\\"7582\\\",\\n\",\n      \"    \\\"orderID\\\": \\\"7580\\\",\\n\",\n      \"    \\\"id\\\": \\\"7582\\\",\\n\",\n      \"    \\\"type\\\": \\\"ORDER_CANCEL\\\",\\n\",\n      \"    \\\"accountID\\\": \\\"101-004-1435156-001\\\",\\n\",\n      \"    \\\"reason\\\": \\\"CLIENT_REQUEST\\\"\\n\",\n      \"  },\\n\",\n      \"  \\\"lastTransactionID\\\": \\\"7582\\\",\\n\",\n      \"  \\\"relatedTransactionIDs\\\": [\\n\",\n      \"    \\\"7582\\\"\\n\",\n      \"  ]\\n\",\n      \"}\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"r = orders.OrdersPending(accountID=accountID)\\n\",\n    \"rv = client.request(r)\\n\",\n    \"idsToCancel = [order.get('id') for order in rv['orders'] if order.get('type') == \\\"TAKE_PROFIT\\\"]\\n\",\n    \"for orderID in idsToCancel:\\n\",\n    \"    r = orders.OrderCancel(accountID=accountID, orderID=orderID)\\n\",\n    \"    rv = client.request(r)\\n\",\n    \"    print(\\\"Request: {} ... response: {}\\\".format(r, json.dumps(rv, indent=2)))\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"source\": [\n    \"### create a LimitOrder with a *GTD* \\\"good-til-date\\\"\\n\",\n    \"\\n\",\n    \"Create a LimitOrder and let it expire: *2018-07-02T00:00:00* using *GTD*. Make sure it is in the future\\n\",\n    \"when you run this example!\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 12,\n   \"metadata\": {\n    \"collapsed\": false,\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"{\\n\",\n      \"    \\\"order\\\": {\\n\",\n      \"        \\\"price\\\": \\\"1.08000\\\",\\n\",\n      \"        \\\"timeInForce\\\": \\\"GTD\\\",\\n\",\n      \"        \\\"positionFill\\\": \\\"DEFAULT\\\",\\n\",\n      \"        \\\"type\\\": \\\"LIMIT\\\",\\n\",\n      \"        \\\"instrument\\\": \\\"EUR_USD\\\",\\n\",\n      \"        \\\"gtdTime\\\": \\\"2018-07-02T00:00:00\\\",\\n\",\n      \"        \\\"units\\\": \\\"10000\\\"\\n\",\n      \"    }\\n\",\n      \"}\\n\",\n      \"{\\n\",\n      \"  \\\"relatedTransactionIDs\\\": [\\n\",\n      \"    \\\"8923\\\"\\n\",\n      \"  ],\\n\",\n      \"  \\\"lastTransactionID\\\": \\\"8923\\\",\\n\",\n      \"  \\\"orderCreateTransaction\\\": {\\n\",\n      \"    \\\"price\\\": \\\"1.08000\\\",\\n\",\n      \"    \\\"triggerCondition\\\": \\\"DEFAULT\\\",\\n\",\n      \"    \\\"positionFill\\\": \\\"DEFAULT\\\",\\n\",\n      \"    \\\"type\\\": \\\"LIMIT_ORDER\\\",\\n\",\n      \"    \\\"requestID\\\": \\\"42440345970496965\\\",\\n\",\n      \"    \\\"partialFill\\\": \\\"DEFAULT\\\",\\n\",\n      \"    \\\"gtdTime\\\": \\\"2018-07-02T04:00:00.000000000Z\\\",\\n\",\n      \"    \\\"batchID\\\": \\\"8923\\\",\\n\",\n      \"    \\\"id\\\": \\\"8923\\\",\\n\",\n      \"    \\\"userID\\\": 1435156,\\n\",\n      \"    \\\"accountID\\\": \\\"101-004-1435156-001\\\",\\n\",\n      \"    \\\"timeInForce\\\": \\\"GTD\\\",\\n\",\n      \"    \\\"reason\\\": \\\"CLIENT_ORDER\\\",\\n\",\n      \"    \\\"instrument\\\": \\\"EUR_USD\\\",\\n\",\n      \"    \\\"time\\\": \\\"2018-06-10T12:06:30.259079220Z\\\",\\n\",\n      \"    \\\"units\\\": \\\"10000\\\"\\n\",\n      \"  }\\n\",\n      \"}\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"from oandapyV20.contrib.requests import LimitOrderRequest\\n\",\n    \"\\n\",\n    \"# make sure GTD_TIME is in the future \\n\",\n    \"# also make sure the price condition is not met\\n\",\n    \"# and specify GTD_TIME as UTC or local\\n\",\n    \"# GTD_TIME=\\\"2018-07-02T00:00:00Z\\\" # UTC\\n\",\n    \"GTD_TIME=\\\"2018-07-02T00:00:00\\\"\\n\",\n    \"ordr = LimitOrderRequest(instrument=\\\"EUR_USD\\\",\\n\",\n    \"                          units=10000,\\n\",\n    \"                          timeInForce=\\\"GTD\\\",\\n\",\n    \"                          gtdTime=GTD_TIME,\\n\",\n    \"                          price=1.08)\\n\",\n    \"print(json.dumps(ordr.data, indent=4))\\n\",\n    \"r = orders.OrderCreate(accountID=accountID, data=ordr.data)\\n\",\n    \"rv = client.request(r)\\n\",\n    \"print(json.dumps(rv, indent=2))\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"source\": [\n    \"### Request the pending orders\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 13,\n   \"metadata\": {\n    \"collapsed\": false,\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"{\\n\",\n      \"  \\\"orders\\\": [\\n\",\n      \"    {\\n\",\n      \"      \\\"price\\\": \\\"1.08000\\\",\\n\",\n      \"      \\\"triggerCondition\\\": \\\"DEFAULT\\\",\\n\",\n      \"      \\\"state\\\": \\\"PENDING\\\",\\n\",\n      \"      \\\"positionFill\\\": \\\"DEFAULT\\\",\\n\",\n      \"      \\\"partialFill\\\": \\\"DEFAULT_FILL\\\",\\n\",\n      \"      \\\"gtdTime\\\": \\\"2018-07-02T04:00:00.000000000Z\\\",\\n\",\n      \"      \\\"id\\\": \\\"8923\\\",\\n\",\n      \"      \\\"timeInForce\\\": \\\"GTD\\\",\\n\",\n      \"      \\\"type\\\": \\\"LIMIT\\\",\\n\",\n      \"      \\\"instrument\\\": \\\"EUR_USD\\\",\\n\",\n      \"      \\\"createTime\\\": \\\"2018-06-10T12:06:30.259079220Z\\\",\\n\",\n      \"      \\\"units\\\": \\\"10000\\\"\\n\",\n      \"    }\\n\",\n      \"  ],\\n\",\n      \"  \\\"lastTransactionID\\\": \\\"8923\\\"\\n\",\n      \"}\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"r = orders.OrdersPending(accountID=accountID)\\n\",\n    \"rv = client.request(r)\\n\",\n    \"print(json.dumps(rv, indent=2))\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"source\": [\n    \"### Cancel the GTD order\\n\",\n    \"\\n\",\n    \"Fetch the *orderID* from the *pending orders* and cancel the order.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 14,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"{\\n\",\n      \"  \\\"relatedTransactionIDs\\\": [\\n\",\n      \"    \\\"8924\\\"\\n\",\n      \"  ],\\n\",\n      \"  \\\"orderCancelTransaction\\\": {\\n\",\n      \"    \\\"accountID\\\": \\\"101-004-1435156-001\\\",\\n\",\n      \"    \\\"time\\\": \\\"2018-06-10T12:07:35.453416669Z\\\",\\n\",\n      \"    \\\"orderID\\\": \\\"8923\\\",\\n\",\n      \"    \\\"reason\\\": \\\"CLIENT_REQUEST\\\",\\n\",\n      \"    \\\"requestID\\\": \\\"42440346243149289\\\",\\n\",\n      \"    \\\"type\\\": \\\"ORDER_CANCEL\\\",\\n\",\n      \"    \\\"batchID\\\": \\\"8924\\\",\\n\",\n      \"    \\\"id\\\": \\\"8924\\\",\\n\",\n      \"    \\\"userID\\\": 1435156\\n\",\n      \"  },\\n\",\n      \"  \\\"lastTransactionID\\\": \\\"8924\\\"\\n\",\n      \"}\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"r = orders.OrderCancel(accountID=accountID, orderID=8923)\\n\",\n    \"rv = client.request(r)\\n\",\n    \"print(json.dumps(rv, indent=2))\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Request pendig orders once again ... the 8923 should be gone\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 15,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"{\\n\",\n      \"  \\\"orders\\\": [],\\n\",\n      \"  \\\"lastTransactionID\\\": \\\"8924\\\"\\n\",\n      \"}\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"r = orders.OrdersPending(accountID=accountID)\\n\",\n    \"rv = client.request(r)\\n\",\n    \"print(json.dumps(rv, indent=2))\"\n   ]\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"Python 3\",\n   \"language\": \"python\",\n   \"name\": \"python3\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.5.2\"\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 2\n}\n"
  },
  {
    "path": "jupyter/positions.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"source\": [\n    \"[index](./index.ipynb) | [accounts](./accounts.ipynb) | [orders](./orders.ipynb) | [trades](./trades.ipynb) | [positions](./positions.ipynb) | [historical](./historical.ipynb) | [streams](./streams.ipynb) | [errors](./exceptions.ipynb)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"source\": [\n    \"## Open Positions\\n\",\n    \"\\n\",\n    \"Lets get the open positions. It should show the total units LONG and SHORT per instrument and the *tradeID's* associated with the position.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 1,\n   \"metadata\": {\n    \"collapsed\": false,\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"Response:  {\\n\",\n      \"  \\\"positions\\\": [\\n\",\n      \"    {\\n\",\n      \"      \\\"pl\\\": \\\"-752.7628\\\",\\n\",\n      \"      \\\"resettablePL\\\": \\\"-752.7628\\\",\\n\",\n      \"      \\\"unrealizedPL\\\": \\\"-128.4516\\\",\\n\",\n      \"      \\\"short\\\": {\\n\",\n      \"        \\\"units\\\": \\\"0\\\",\\n\",\n      \"        \\\"pl\\\": \\\"-101.7859\\\",\\n\",\n      \"        \\\"resettablePL\\\": \\\"-101.7859\\\",\\n\",\n      \"        \\\"unrealizedPL\\\": \\\"0.0000\\\"\\n\",\n      \"      },\\n\",\n      \"      \\\"instrument\\\": \\\"EUR_USD\\\",\\n\",\n      \"      \\\"long\\\": {\\n\",\n      \"        \\\"units\\\": \\\"50000\\\",\\n\",\n      \"        \\\"pl\\\": \\\"-650.9769\\\",\\n\",\n      \"        \\\"resettablePL\\\": \\\"-650.9769\\\",\\n\",\n      \"        \\\"averagePrice\\\": \\\"1.05836\\\",\\n\",\n      \"        \\\"unrealizedPL\\\": \\\"-128.4516\\\",\\n\",\n      \"        \\\"tradeIDs\\\": [\\n\",\n      \"          \\\"4224\\\",\\n\",\n      \"          \\\"7558\\\",\\n\",\n      \"          \\\"7562\\\",\\n\",\n      \"          \\\"7572\\\",\\n\",\n      \"          \\\"7579\\\"\\n\",\n      \"        ]\\n\",\n      \"      }\\n\",\n      \"    }\\n\",\n      \"  ],\\n\",\n      \"  \\\"lastTransactionID\\\": \\\"7582\\\"\\n\",\n      \"}\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"import json\\n\",\n    \"import oandapyV20\\n\",\n    \"import oandapyV20.endpoints.positions as positions\\n\",\n    \"from exampleauth import exampleauth\\n\",\n    \"\\n\",\n    \"accountID, access_token = exampleauth.exampleAuth()\\n\",\n    \"client = oandapyV20.API(access_token=access_token)\\n\",\n    \"\\n\",\n    \"r = positions.OpenPositions(accountID=accountID)\\n\",\n    \"rv = client.request(r)\\n\",\n    \"print(\\\"Response: \\\", json.dumps(rv, indent=2))\"\n   ]\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"Python 3\",\n   \"language\": \"python\",\n   \"name\": \"python3\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.5.2\"\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 2\n}\n"
  },
  {
    "path": "jupyter/streams.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"source\": [\n    \"[index](./index.ipynb) | [accounts](./accounts.ipynb) | [orders](./orders.ipynb) | [trades](./trades.ipynb) | [positions](./positions.ipynb) | [historical](./historical.ipynb) | [streams](./streams.ipynb) | [errors](./exceptions.ipynb)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"source\": [\n    \"## Streaming data (prices & events)\\n\",\n    \"\\n\",\n    \"The REST-V20 API offers *streaming prices* and *streaming events*. Both can be simply accessed as the next example will show.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 2,\n   \"metadata\": {\n    \"collapsed\": false,\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"{'asks': [{'liquidity': 10000000.0, 'price': '1.05534'}, {'liquidity': 10000000.0, 'price': '1.05536'}], 'tradeable': True, 'instrument': 'EUR_USD', 'type': 'PRICE', 'closeoutAsk': '1.05538', 'closeoutBid': '1.05518', 'time': '2017-03-09T13:37:46.048197280Z', 'status': 'tradeable', 'bids': [{'liquidity': 10000000.0, 'price': '1.05522'}, {'liquidity': 10000000.0, 'price': '1.05520'}]}\\n\",\n      \"{'asks': [{'liquidity': 1000000.0, 'price': '120.991'}, {'liquidity': 2000000.0, 'price': '120.992'}, {'liquidity': 5000000.0, 'price': '120.993'}, {'liquidity': 10000000.0, 'price': '120.995'}], 'tradeable': True, 'instrument': 'EUR_JPY', 'type': 'PRICE', 'closeoutAsk': '120.995', 'closeoutBid': '120.965', 'time': '2017-03-09T13:37:44.958026355Z', 'status': 'tradeable', 'bids': [{'liquidity': 1000000.0, 'price': '120.969'}, {'liquidity': 2000000.0, 'price': '120.968'}, {'liquidity': 5000000.0, 'price': '120.967'}, {'liquidity': 10000000.0, 'price': '120.965'}]}\\n\",\n      \"{'asks': [{'liquidity': 1000000.0, 'price': '120.995'}, {'liquidity': 2000000.0, 'price': '120.996'}, {'liquidity': 5000000.0, 'price': '120.997'}, {'liquidity': 10000000.0, 'price': '120.999'}], 'tradeable': True, 'instrument': 'EUR_JPY', 'type': 'PRICE', 'closeoutAsk': '120.999', 'closeoutBid': '120.971', 'time': '2017-03-09T13:37:47.550550833Z', 'status': 'tradeable', 'bids': [{'liquidity': 1000000.0, 'price': '120.975'}, {'liquidity': 2000000.0, 'price': '120.974'}, {'liquidity': 5000000.0, 'price': '120.973'}, {'liquidity': 10000000.0, 'price': '120.971'}]}\\n\",\n      \"{'asks': [{'liquidity': 10000000.0, 'price': '1.05527'}, {'liquidity': 10000000.0, 'price': '1.05529'}], 'tradeable': True, 'instrument': 'EUR_USD', 'type': 'PRICE', 'closeoutAsk': '1.05531', 'closeoutBid': '1.05510', 'time': '2017-03-09T13:37:49.349544372Z', 'status': 'tradeable', 'bids': [{'liquidity': 10000000.0, 'price': '1.05514'}, {'liquidity': 10000000.0, 'price': '1.05512'}]}\\n\",\n      \"Stream processing ended because we made it stop after 3 ticks\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"import json\\n\",\n    \"import oandapyV20\\n\",\n    \"import oandapyV20.endpoints.pricing as pricing\\n\",\n    \"from oandapyV20.exceptions import StreamTerminated\\n\",\n    \"from exampleauth import exampleauth\\n\",\n    \"\\n\",\n    \"accountID, access_token = exampleauth.exampleAuth()\\n\",\n    \"client = oandapyV20.API(access_token=access_token)\\n\",\n    \"\\n\",\n    \"instruments = [\\\"EUR_USD\\\", \\\"EUR_JPY\\\"]\\n\",\n    \"r = pricing.PricingStream(accountID=accountID, params={\\\"instruments\\\": \\\",\\\".join(instruments)})\\n\",\n    \"\\n\",\n    \"n = 0\\n\",\n    \"stopAfter = 3 # let's terminate after receiving 3 ticks\\n\",\n    \"try:\\n\",\n    \"    # the stream requests returns a generator so we can do ...\\n\",\n    \"    for tick in client.request(r):\\n\",\n    \"        print(tick)\\n\",\n    \"        if n >= stopAfter:\\n\",\n    \"            r.terminate()\\n\",\n    \"        n += 1\\n\",\n    \"        \\n\",\n    \"except StreamTerminated as err:\\n\",\n    \"    print(\\\"Stream processing ended because we made it stop after {} ticks\\\".format(n))\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 4,\n   \"metadata\": {\n    \"collapsed\": false,\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"{'lastTransactionID': '7582', 'time': '2017-03-09T15:08:57.512620407Z', 'type': 'HEARTBEAT'}\\n\",\n      \"{'lastTransactionID': '7582', 'time': '2017-03-09T15:09:02.594588344Z', 'type': 'HEARTBEAT'}\\n\",\n      \"{'lastTransactionID': '7582', 'time': '2017-03-09T15:09:07.657436396Z', 'type': 'HEARTBEAT'}\\n\",\n      \"{'lastTransactionID': '7582', 'time': '2017-03-09T15:09:12.721645564Z', 'type': 'HEARTBEAT'}\\n\",\n      \"Stream processing ended because we made it stop after 3 ticks\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"import json\\n\",\n    \"import oandapyV20\\n\",\n    \"import oandapyV20.endpoints.transactions as trans\\n\",\n    \"from oandapyV20.exceptions import StreamTerminated\\n\",\n    \"from exampleauth import exampleauth\\n\",\n    \"\\n\",\n    \"accountID, access_token = exampleauth.exampleAuth()\\n\",\n    \"client = oandapyV20.API(access_token=access_token)\\n\",\n    \"\\n\",\n    \"instruments = [\\\"EUR_USD\\\", \\\"EUR_JPY\\\"]\\n\",\n    \"r = trans.TransactionsStream(accountID=accountID)\\n\",\n    \"\\n\",\n    \"n = 0\\n\",\n    \"stopAfter = 3 # let's terminate after receiving 3 ticks\\n\",\n    \"try:\\n\",\n    \"    # the stream requests returns a generator so we can do ...\\n\",\n    \"    for T in client.request(r):\\n\",\n    \"        print(T)\\n\",\n    \"        if n >= stopAfter:\\n\",\n    \"            r.terminate()\\n\",\n    \"        n += 1\\n\",\n    \"        \\n\",\n    \"except StreamTerminated as err:\\n\",\n    \"    print(\\\"Stream processing ended because we made it stop after {} ticks\\\".format(n))\"\n   ]\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"Python 3\",\n   \"language\": \"python\",\n   \"name\": \"python3\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.5.2\"\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 2\n}\n"
  },
  {
    "path": "jupyter/token.txt",
    "content": "aaaabbbbccccddddeeeeffffaaaabbbb-ccccbbbbaaaaeeeebbbbaaaaffffbbbb\n"
  },
  {
    "path": "jupyter/trades.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"source\": [\n    \"[index](./index.ipynb) | [accounts](./accounts.ipynb) | [orders](./orders.ipynb) | [trades](./trades.ipynb) | [positions](./positions.ipynb) | [historical](./historical.ipynb) | [streams](./streams.ipynb) | [errors](./exceptions.ipynb)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"source\": [\n    \"##  Open Trades\\n\",\n    \"\\n\",\n    \"The previously executed Market-Order resulted in a *trade: LONG 10000 EUR_USD*. This results also in a *Position*.\\n\",\n    \"The position will be 10000 units also unless there were other trades opened in the same instrument. In that case the last 10000 units will be added to it. \\n\",\n    \"\\n\",\n    \"Example: get the open trades. The trade that was opened has the id 7562. It should be in the list of trades that we get by performing an OpenTrades request. \"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 2,\n   \"metadata\": {\n    \"collapsed\": false,\n    \"deletable\": true,\n    \"editable\": true\n   },\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"Response:  {\\n\",\n      \"  \\\"lastTransactionID\\\": \\\"7582\\\",\\n\",\n      \"  \\\"trades\\\": [\\n\",\n      \"    {\\n\",\n      \"      \\\"state\\\": \\\"OPEN\\\",\\n\",\n      \"      \\\"financing\\\": \\\"0.0000\\\",\\n\",\n      \"      \\\"stopLossOrder\\\": {\\n\",\n      \"        \\\"state\\\": \\\"PENDING\\\",\\n\",\n      \"        \\\"timeInForce\\\": \\\"GTC\\\",\\n\",\n      \"        \\\"price\\\": \\\"1.05000\\\",\\n\",\n      \"        \\\"triggerCondition\\\": \\\"TRIGGER_DEFAULT\\\",\\n\",\n      \"        \\\"createTime\\\": \\\"2017-03-09T13:22:13.832587780Z\\\",\\n\",\n      \"        \\\"id\\\": \\\"7581\\\",\\n\",\n      \"        \\\"type\\\": \\\"STOP_LOSS\\\",\\n\",\n      \"        \\\"tradeID\\\": \\\"7579\\\"\\n\",\n      \"      },\\n\",\n      \"      \\\"realizedPL\\\": \\\"0.0000\\\",\\n\",\n      \"      \\\"price\\\": \\\"1.05563\\\",\\n\",\n      \"      \\\"unrealizedPL\\\": \\\"-0.8526\\\",\\n\",\n      \"      \\\"instrument\\\": \\\"EUR_USD\\\",\\n\",\n      \"      \\\"initialUnits\\\": \\\"10000\\\",\\n\",\n      \"      \\\"id\\\": \\\"7579\\\",\\n\",\n      \"      \\\"openTime\\\": \\\"2017-03-09T13:22:13.832587780Z\\\",\\n\",\n      \"      \\\"currentUnits\\\": \\\"10000\\\"\\n\",\n      \"    },\\n\",\n      \"    {\\n\",\n      \"      \\\"state\\\": \\\"OPEN\\\",\\n\",\n      \"      \\\"financing\\\": \\\"0.0000\\\",\\n\",\n      \"      \\\"stopLossOrder\\\": {\\n\",\n      \"        \\\"state\\\": \\\"PENDING\\\",\\n\",\n      \"        \\\"timeInForce\\\": \\\"GTC\\\",\\n\",\n      \"        \\\"price\\\": \\\"1.05000\\\",\\n\",\n      \"        \\\"triggerCondition\\\": \\\"TRIGGER_DEFAULT\\\",\\n\",\n      \"        \\\"createTime\\\": \\\"2017-03-09T11:45:48.928448770Z\\\",\\n\",\n      \"        \\\"id\\\": \\\"7574\\\",\\n\",\n      \"        \\\"type\\\": \\\"STOP_LOSS\\\",\\n\",\n      \"        \\\"tradeID\\\": \\\"7572\\\"\\n\",\n      \"      },\\n\",\n      \"      \\\"realizedPL\\\": \\\"0.0000\\\",\\n\",\n      \"      \\\"price\\\": \\\"1.05580\\\",\\n\",\n      \"      \\\"unrealizedPL\\\": \\\"-2.4632\\\",\\n\",\n      \"      \\\"instrument\\\": \\\"EUR_USD\\\",\\n\",\n      \"      \\\"initialUnits\\\": \\\"10000\\\",\\n\",\n      \"      \\\"id\\\": \\\"7572\\\",\\n\",\n      \"      \\\"openTime\\\": \\\"2017-03-09T11:45:48.928448770Z\\\",\\n\",\n      \"      \\\"currentUnits\\\": \\\"10000\\\"\\n\",\n      \"    },\\n\",\n      \"    {\\n\",\n      \"      \\\"state\\\": \\\"OPEN\\\",\\n\",\n      \"      \\\"financing\\\": \\\"-0.2693\\\",\\n\",\n      \"      \\\"stopLossOrder\\\": {\\n\",\n      \"        \\\"state\\\": \\\"PENDING\\\",\\n\",\n      \"        \\\"timeInForce\\\": \\\"GTC\\\",\\n\",\n      \"        \\\"price\\\": \\\"1.05000\\\",\\n\",\n      \"        \\\"triggerCondition\\\": \\\"TRIGGER_DEFAULT\\\",\\n\",\n      \"        \\\"createTime\\\": \\\"2017-03-07T09:18:51.563637768Z\\\",\\n\",\n      \"        \\\"id\\\": \\\"7564\\\",\\n\",\n      \"        \\\"type\\\": \\\"STOP_LOSS\\\",\\n\",\n      \"        \\\"tradeID\\\": \\\"7562\\\"\\n\",\n      \"      },\\n\",\n      \"      \\\"realizedPL\\\": \\\"0.0000\\\",\\n\",\n      \"      \\\"price\\\": \\\"1.05837\\\",\\n\",\n      \"      \\\"unrealizedPL\\\": \\\"-26.8109\\\",\\n\",\n      \"      \\\"instrument\\\": \\\"EUR_USD\\\",\\n\",\n      \"      \\\"initialUnits\\\": \\\"10000\\\",\\n\",\n      \"      \\\"id\\\": \\\"7562\\\",\\n\",\n      \"      \\\"openTime\\\": \\\"2017-03-07T09:18:51.563637768Z\\\",\\n\",\n      \"      \\\"currentUnits\\\": \\\"10000\\\"\\n\",\n      \"    },\\n\",\n      \"    {\\n\",\n      \"      \\\"state\\\": \\\"OPEN\\\",\\n\",\n      \"      \\\"financing\\\": \\\"-0.2706\\\",\\n\",\n      \"      \\\"stopLossOrder\\\": {\\n\",\n      \"        \\\"state\\\": \\\"PENDING\\\",\\n\",\n      \"        \\\"timeInForce\\\": \\\"GTC\\\",\\n\",\n      \"        \\\"price\\\": \\\"1.05000\\\",\\n\",\n      \"        \\\"triggerCondition\\\": \\\"TRIGGER_DEFAULT\\\",\\n\",\n      \"        \\\"createTime\\\": \\\"2017-03-07T09:08:04.219010730Z\\\",\\n\",\n      \"        \\\"id\\\": \\\"7560\\\",\\n\",\n      \"        \\\"type\\\": \\\"STOP_LOSS\\\",\\n\",\n      \"        \\\"tradeID\\\": \\\"7558\\\"\\n\",\n      \"      },\\n\",\n      \"      \\\"realizedPL\\\": \\\"0.0000\\\",\\n\",\n      \"      \\\"price\\\": \\\"1.05820\\\",\\n\",\n      \"      \\\"unrealizedPL\\\": \\\"-25.2004\\\",\\n\",\n      \"      \\\"instrument\\\": \\\"EUR_USD\\\",\\n\",\n      \"      \\\"initialUnits\\\": \\\"10000\\\",\\n\",\n      \"      \\\"id\\\": \\\"7558\\\",\\n\",\n      \"      \\\"openTime\\\": \\\"2017-03-07T09:08:04.219010730Z\\\",\\n\",\n      \"      \\\"currentUnits\\\": \\\"10000\\\"\\n\",\n      \"    },\\n\",\n      \"    {\\n\",\n      \"      \\\"state\\\": \\\"OPEN\\\",\\n\",\n      \"      \\\"financing\\\": \\\"-4.7102\\\",\\n\",\n      \"      \\\"realizedPL\\\": \\\"0.0000\\\",\\n\",\n      \"      \\\"price\\\": \\\"1.06381\\\",\\n\",\n      \"      \\\"unrealizedPL\\\": \\\"-78.3485\\\",\\n\",\n      \"      \\\"instrument\\\": \\\"EUR_USD\\\",\\n\",\n      \"      \\\"initialUnits\\\": \\\"10000\\\",\\n\",\n      \"      \\\"id\\\": \\\"4224\\\",\\n\",\n      \"      \\\"openTime\\\": \\\"2017-02-10T21:50:02.670154087Z\\\",\\n\",\n      \"      \\\"currentUnits\\\": \\\"10000\\\"\\n\",\n      \"    }\\n\",\n      \"  ]\\n\",\n      \"}\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"import json\\n\",\n    \"import oandapyV20\\n\",\n    \"import oandapyV20.endpoints.trades as trades\\n\",\n    \"from exampleauth import exampleauth\\n\",\n    \"\\n\",\n    \"accountID, access_token = exampleauth.exampleAuth()\\n\",\n    \"client = oandapyV20.API(access_token=access_token)\\n\",\n    \"\\n\",\n    \"r = trades.OpenTrades(accountID=accountID)\\n\",\n    \"rv = client.request(r)\\n\",\n    \"print(\\\"Response: \\\", json.dumps(rv, indent=2))\"\n   ]\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"Python 3\",\n   \"language\": \"python\",\n   \"name\": \"python3\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.5.2\"\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 2\n}\n"
  },
  {
    "path": "oandapyV20/__init__.py",
    "content": "import logging\nfrom .oandapyV20 import API\nfrom .exceptions import V20Error\n\n__title__ = \"OANDA REST V20 API Wrapper\"\n__version__ = \"0.7.2\"\n__author__ = \"Feite Brekeveld\"\n__license__ = \"MIT\"\n__copyright__ = \"Copyright 2016 - 2018 Feite Brekeveld\"\n\n# Version synonym\nVERSION = __version__\n\n# Set default logging handler to avoid \"No handler found\" warnings.\ntry:\n    from logging import NullHandler\nexcept ImportError:\n    class NullHandler(logging.Handler):\n        def emit(self, record):\n            pass\n\nlogging.getLogger(__name__).addHandler(NullHandler())\n\n__all__ = (\n    'API',\n    'V20Error'\n)\n"
  },
  {
    "path": "oandapyV20/contrib/__init__.py",
    "content": ""
  },
  {
    "path": "oandapyV20/contrib/factories/__init__.py",
    "content": "from .history import InstrumentsCandlesFactory\n\n__all__ = (\n    'InstrumentsCandlesFactory',\n)\n"
  },
  {
    "path": "oandapyV20/contrib/factories/history.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom datetime import datetime\nimport calendar\nimport logging\n\nimport oandapyV20.endpoints.instruments as instruments\nfrom oandapyV20.contrib.generic import granularity_to_time, secs2time\n\n\nlogger = logging.getLogger(__name__)\n\nMAX_BATCH = 5000\nDEFAULT_BATCH = 500\n\n\ndef InstrumentsCandlesFactory(instrument, params=None):\n    \"\"\"InstrumentsCandlesFactory - generate InstrumentCandles requests.\n\n    InstrumentsCandlesFactory is used to retrieve historical data by\n    automatically generating consecutive requests when the OANDA limit\n    of *count* records is exceeded.\n\n    This is known by calculating the number of candles between *from* and\n    *to*. If *to* is not specified *to* will be equal to *now*.\n\n    The *count* parameter is only used to control the number of records to\n    retrieve in a single request.\n\n    The *includeFirst* parameter is forced to make sure that results do\n    no have a 1-record gap between consecutive requests.\n\n    Parameters\n    ----------\n\n    instrument : string (required)\n        the instrument to create the order for\n\n    params: params (optional)\n        the parameters to specify the historical range,\n        see the REST-V20 docs regarding 'instrument' at developer.oanda.com\n        If no params are specified, just a single InstrumentsCandles request\n        will be generated acting the same as if you had just created it\n        directly.\n\n    Example\n    -------\n\n    The *oandapyV20.API* client processes requests as objects. So,\n    downloading large historical batches simply comes down to:\n\n    >>> import json\n    >>> from oandapyV20 import API\n    >>> from oandapyV20.contrib.factories import InstrumentsCandlesFactory\n    >>>\n    >>> client = API(access_token=...)\n    >>> instrument, granularity = \"EUR_USD\", \"M15\"\n    >>> _from = \"2017-01-01T00:00:00Z\"\n    >>> params = {\n    ...    \"from\": _from,\n    ...    \"granularity\": granularity,\n    ...    \"count\": 2500,\n    ... }\n    >>> with open(\"/tmp/{}.{}\".format(instrument, granularity), \"w\") as OUT:\n    >>>     # The factory returns a generator generating consecutive\n    >>>     # requests to retrieve full history from date 'from' till 'to'\n    >>>     for r in InstrumentsCandlesFactory(instrument=instrument,\n    ...                                        params=params)\n    >>>         client.request(r)\n    >>>         OUT.write(json.dumps(r.response.get('candles'), indent=2))\n\n    .. note:: Normally you can't combine *from*, *to* and *count*.\n              When *count* specified, it is used to calculate the gap between\n              *to* and *from*. The *params* passed to the generated request\n              itself does contain the *count* parameter.\n\n    \"\"\"\n    RFC3339 = \"%Y-%m-%dT%H:%M:%SZ\"\n\n    # if not specified use the default of 'S5' as OANDA does\n    gs = granularity_to_time(params.get('granularity', 'S5'))\n\n    _from = None\n    _epoch_from = None\n    if 'from' in params:\n        _from = datetime.strptime(params.get('from'), RFC3339)\n        _epoch_from = int(calendar.timegm(_from.timetuple()))\n\n    _to = datetime.utcnow()\n    if 'to' in params:\n        _tmp = datetime.strptime(params.get('to'), RFC3339)\n        # if specified datetime > now, we use 'now' instead\n        if _tmp > _to:\n            logger.info(\"datetime %s is in the future, will be set to 'now'\",\n                        params.get('to'))\n        else:\n            _to = _tmp\n\n    _epoch_to = int(calendar.timegm(_to.timetuple()))\n\n    _count = params.get('count', DEFAULT_BATCH)\n    # OANDA will respond with a V20Error if count > MAX_BATCH\n\n    if 'to' in params and 'from' not in params:\n        raise ValueError(\"'to' specified without 'from'\")\n\n    if not params or 'from' not in params:\n        yield instruments.InstrumentsCandles(instrument=instrument,\n                                             params=params)\n\n    else:\n        delta = _epoch_to - _epoch_from\n        nbars = delta / gs\n\n        cpparams = params.copy()\n        for k in ['count', 'from', 'to']:\n            if k in cpparams:\n                del cpparams[k]\n        # force includeFirst\n        cpparams.update({\"includeFirst\": True})\n\n        # generate InstrumentsCandles requests for all 'bars', each request\n        # requesting max. count records\n        for _ in range(_count, int(((nbars//_count)+1))*_count+1, _count):\n            to = _epoch_from + _count * gs\n            if to > _epoch_to:\n                to = _epoch_to\n            yparams = cpparams.copy()\n            yparams.update({\"from\": secs2time(_epoch_from).strftime(RFC3339)})\n            yparams.update({\"to\": secs2time(to).strftime(RFC3339)})\n            yield instruments.InstrumentsCandles(instrument=instrument,\n                                                 params=yparams)\n            _epoch_from = to\n"
  },
  {
    "path": "oandapyV20/contrib/generic.py",
    "content": "import re\nimport time\nfrom datetime import datetime\n\n\ndef secs2time(e):\n    \"\"\"secs2time - convert epoch to datetime.\n\n    >>> d = secs2time(1497499200)\n    >>> d\n    datetime.datetime(2017, 6, 15, 4, 0)\n    >>> d.strftime(\"%Y%m%d-%H:%M:%S\")\n    '20170615-04:00:00'\n    \"\"\"\n    w = time.gmtime(e)\n    return datetime(*list(w)[0:6])\n\n\ndef granularity_to_time(s):\n    \"\"\"convert a named granularity into seconds.\n\n    get value in seconds for named granularities: M1, M5 ... H1 etc.\n\n    >>> print(granularity_to_time(\"M5\"))\n    300\n    \"\"\"\n    mfact = {\n        'S': 1,\n        'M': 60,\n        'H': 3600,\n        'D': 86400,\n        'W': 604800,\n    }\n    try:\n        f, n = re.match(\"(?P<f>[SMHDW])(?:(?P<n>\\d+)|)\", s).groups()\n        n = n if n else 1\n        return mfact[f] * int(n)\n\n    except Exception as e:\n        raise ValueError(e)\n"
  },
  {
    "path": "oandapyV20/contrib/requests/__init__.py",
    "content": "from .marketorder import MarketOrderRequest\nfrom .limitorder import LimitOrderRequest\nfrom .mitorder import MITOrderRequest\nfrom .takeprofitorder import TakeProfitOrderRequest\nfrom .stoplossorder import StopLossOrderRequest\nfrom .trailingstoplossorder import TrailingStopLossOrderRequest\nfrom .stoporder import StopOrderRequest\nfrom .positionclose import PositionCloseRequest\nfrom .tradeclose import TradeCloseRequest\n\nfrom .onfill import (\n    TakeProfitDetails,\n    StopLossDetails,\n    TrailingStopLossDetails\n)\nfrom .extensions import ClientExtensions\n\n__all__ = (\n    'MarketOrderRequest',\n    'LimitOrderRequest',\n    'MITOrderRequest',\n    'TakeProfitOrderRequest',\n    'StopLossOrderRequest',\n    'TrailingStopLossOrderRequest',\n    'StopOrderRequest',\n    'PositionCloseRequest',\n    'TradeCloseRequest',\n    'TakeProfitDetails',\n    'StopLossDetails',\n    'TrailingStopLossDetails',\n    'ClientExtensions',\n)\n"
  },
  {
    "path": "oandapyV20/contrib/requests/baserequest.py",
    "content": "# -*- coding: utf-8 -*-\n\"\"\"baserequest.\"\"\"\n\nimport json\nimport six\nfrom abc import ABCMeta, abstractmethod\n\n\n@six.add_metaclass(ABCMeta)\nclass BaseRequest(object):\n    \"\"\"baseclass for request classes.\"\"\"\n\n    @abstractmethod\n    def __init__(self):\n        self._data = dict()\n\n    def __repr__(self):\n        return json.dumps(self.__dict__)\n\n    @property\n    def data(self):\n        \"\"\"data - return the JSON body.\n\n        The data property returns a dict representing the\n        JSON-body needed for the API-request. All values that are\n        not set will be left out\n        \"\"\"\n        d = dict()\n        for k, v in self._data.items():\n            # skip unset properties\n            if v is None:\n                continue\n\n            d.update({k: v})\n\n        return d\n\n    def toJSON(self):\n        return json.dumps(self,\n                          default=lambda o: o.__dict__,\n                          sort_keys=True,\n                          indent=4)\n"
  },
  {
    "path": "oandapyV20/contrib/requests/extensions.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom .baserequest import BaseRequest\nfrom oandapyV20.types import ClientID, ClientTag, ClientComment\n\n\nclass ClientExtensions(BaseRequest):\n    \"\"\"Representation of the ClientExtensions.\"\"\"\n\n    def __init__(self,\n                 clientID=None,\n                 clientTag=None,\n                 clientComment=None):\n        \"\"\"Instantiate ClientExtensions.\n\n        Parameters\n        ----------\n\n        clientID : clientID (required)\n            the clientID\n\n        clientTag : clientTag (required)\n            the clientTag\n\n        clientComment : clientComment (required)\n            the clientComment\n\n\n        Example\n        -------\n\n            >>> import json\n            >>> from oandapyV20 import API\n            >>> import oandapyV20.endpoints.orders as orders\n            >>> from oandapyV20.contrib.requests import (\n            ...     MarketOrderRequest, TakeProfitDetails, ClientExtensions)\n            >>>\n            >>> accountID = \"...\"\n            >>> client = API(access_token=...)\n            >>> # at time of writing EUR_USD = 1.0740\n            >>> # let us take profit at 1.10, GoodTillCancel (default)\n            >>> # add clientExtensions to it also\n            >>> takeProfitOnFillOrder = TakeProfitDetails(\n            ...     price=1.10,\n            ...     clientExtensions=ClientExtensions(clientTag=\"mytag\").data)\n            >>> print(takeProfitOnFillOrder.data)\n            {\n                'timeInForce': 'GTC',\n                'price\": '1.10000',\n                'clientExtensions': {'tag': 'mytag'}\n            }\n            >>> ordr = MarketOrderRequest(\n            ...     instrument=\"EUR_USD\",\n            ...     units=10000,\n            ...     takeProfitOnFill=takeProfitOnFillOrder.data\n            ... )\n            >>> # or as shortcut ...\n            >>> #   takeProfitOnFill=TakeProfitDetails(price=1.10).data\n            >>> print(json.dumps(ordr.data, indent=4))\n            >>> r = orders.OrderCreate(accountID, data=ordr.data)\n            >>> rv = client.request(r)\n            >>> ...\n        \"\"\"\n        super(ClientExtensions, self).__init__()\n        if not (clientID or clientTag or clientComment):\n            raise ValueError(\"clientID, clientTag, clientComment required\")\n\n        if clientID:\n            self._data.update({\"id\": ClientID(clientID).value})\n\n        if clientTag:\n            self._data.update({\"tag\": ClientTag(clientTag).value})\n\n        if clientComment:\n            self._data.update({\"comment\": ClientComment(clientComment).value})\n"
  },
  {
    "path": "oandapyV20/contrib/requests/limitorder.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom .baserequest import BaseRequest\nfrom oandapyV20.types import Units, PriceValue\nfrom oandapyV20.definitions.orders import (\n    OrderType,\n    TimeInForce,\n    OrderPositionFill)\n\n\nclass LimitOrderRequest(BaseRequest):\n    \"\"\"create a LimitOrderRequest.\n\n    LimitOrderRequest is used to build the body for a LimitOrder.\n    The body can be used to pass to the OrderCreate endpoint.\n    \"\"\"\n\n    def __init__(self,\n                 instrument,\n                 units,\n                 price,\n                 positionFill=OrderPositionFill.DEFAULT,\n                 clientExtensions=None,\n                 takeProfitOnFill=None,\n                 timeInForce=TimeInForce.GTC,\n                 gtdTime=None,\n                 stopLossOnFill=None,\n                 trailingStopLossOnFill=None,\n                 tradeClientExtensions=None):\n        \"\"\"\n        Instantiate a LimitOrderRequest.\n\n        Parameters\n        ----------\n\n        instrument : string (required)\n            the instrument to create the order for\n\n        units: integer (required)\n            the number of units. If positive the order results in a LONG\n            order. If negative the order results in a SHORT order\n\n        price: float (required)\n            the price indicating the limit.\n\n        Example\n        -------\n\n        >>> import json\n        >>> from oandapyV20 import API\n        >>> import oandapyV20.endpoints.orders as orders\n        >>> from oandapyV20.contrib.requests import LimitOrderRequest\n        >>>\n        >>> accountID = \"...\"\n        >>> client = API(access_token=...)\n        >>> ordr = LimitOrderRequest(instrument=\"EUR_USD\",\n        ...                          units=10000, price=1.08)\n        >>> print(json.dumps(ordr.data, indent=4))\n        {\n            \"order\": {\n                \"timeInForce\": \"GTC\",\n                \"instrument\": \"EUR_USD\",\n                \"units\": \"10000\",\n                \"price\": \"1.08000\",\n                \"type\": \"LIMIT\",\n                \"positionFill\": \"DEFAULT\"\n            }\n        }\n        >>> r = orders.orderCreate(accountID, data=ordr.data)\n        >>> rv = client.request(r)\n        >>>\n        \"\"\"\n        super(LimitOrderRequest, self).__init__()\n\n        # by default for a LIMIT order\n        self._data.update({\"type\": OrderType.LIMIT})\n        self._data.update({\"timeInForce\": timeInForce})\n\n        # required\n        self._data.update({\"instrument\": instrument})\n        self._data.update({\"units\": Units(units).value})\n        self._data.update({\"price\": PriceValue(price).value})\n\n        # optional, but required if timeInForce.GTD\n        self._data.update({\"gtdTime\": gtdTime})\n        if timeInForce == TimeInForce.GTD and not gtdTime:\n            raise ValueError(\"gtdTime missing\")\n\n        # optional\n        self._data.update({\"positionFill\": positionFill})\n        self._data.update({\"clientExtensions\": clientExtensions})\n        self._data.update({\"takeProfitOnFill\": takeProfitOnFill})\n        self._data.update({\"stopLossOnFill\": stopLossOnFill})\n        self._data.update({\"trailingStopLossOnFill\": trailingStopLossOnFill})\n        self._data.update({\"tradeClientExtensions\": tradeClientExtensions})\n\n    @property\n    def data(self):\n        \"\"\"data property.\n\n        return the JSON order body\n        \"\"\"\n        return dict({\"order\": super(LimitOrderRequest, self).data})\n"
  },
  {
    "path": "oandapyV20/contrib/requests/marketorder.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom .baserequest import BaseRequest\nfrom oandapyV20.types import Units, PriceValue\nfrom oandapyV20.definitions.orders import (\n    OrderType,\n    TimeInForce,\n    OrderPositionFill)\n\n\nclass MarketOrderRequest(BaseRequest):\n    \"\"\"create a MarketOrderRequest.\n\n    MarketOrderRequest is used to build the body for a MarketOrder.\n    The body can be used to pass to the OrderCreate endpoint.\n    \"\"\"\n\n    def __init__(self,\n                 instrument,\n                 units,\n                 priceBound=None,\n                 positionFill=OrderPositionFill.DEFAULT,\n                 clientExtensions=None,\n                 takeProfitOnFill=None,\n                 timeInForce=TimeInForce.FOK,\n                 stopLossOnFill=None,\n                 trailingStopLossOnFill=None,\n                 tradeClientExtensions=None):\n        \"\"\"\n        Instantiate a MarketOrderRequest.\n\n        Parameters\n        ----------\n\n        instrument : string (required)\n            the instrument to create the order for\n\n        units: integer (required)\n            the number of units. If positive the order results in a LONG\n            order. If negative the order results in a SHORT order\n\n\n        Example\n        -------\n\n        >>> import json\n        >>> from oandapyV20 import API\n        >>> import oandapyV20.endpoints.orders as orders\n        >>> from oandapyV20.contrib.requests import MarketOrderRequest\n        >>>\n        >>> accountID = \"...\"\n        >>> client = API(access_token=...)\n        >>> mo = MarketOrderRequest(instrument=\"EUR_USD\", units=10000)\n        >>> print(json.dumps(mo.data, indent=4))\n        {\n            \"order\": {\n                \"type\": \"MARKET\",\n                \"positionFill\": \"DEFAULT\",\n                \"instrument\": \"EUR_USD\",\n                \"timeInForce\": \"FOK\",\n                \"units\": \"10000\"\n            }\n        }\n        >>> # now we have the order specification, create the order request\n        >>> r = orders.OrderCreate(accountID, data=mo.data)\n        >>> # perform the request\n        >>> rv = client.request(r)\n        >>> print(rv)\n        >>> print(json.dumps(rv, indent=4))\n        {\n            \"orderFillTransaction\": {\n                \"reason\": \"MARKET_ORDER\",\n                \"pl\": \"0.0000\",\n                \"accountBalance\": \"97864.8813\",\n                \"units\": \"10000\",\n                \"instrument\": \"EUR_USD\",\n                \"accountID\": \"101-004-1435156-001\",\n                \"time\": \"2016-11-11T19:59:43.253587917Z\",\n                \"type\": \"ORDER_FILL\",\n                \"id\": \"2504\",\n                \"financing\": \"0.0000\",\n                \"tradeOpened\": {\n                    \"tradeID\": \"2504\",\n                    \"units\": \"10000\"\n                },\n                \"orderID\": \"2503\",\n                \"userID\": 1435156,\n                \"batchID\": \"2503\",\n                \"price\": \"1.08463\"\n            },\n            \"lastTransactionID\": \"2504\",\n            \"relatedTransactionIDs\": [\n                \"2503\",\n                \"2504\"\n            ],\n            \"orderCreateTransaction\": {\n                \"type\": \"MARKET_ORDER\",\n                \"reason\": \"CLIENT_ORDER\",\n                \"id\": \"2503\",\n                \"timeInForce\": \"FOK\",\n                \"units\": \"10000\",\n                \"time\": \"2016-11-11T19:59:43.253587917Z\",\n                \"positionFill\": \"DEFAULT\",\n                \"accountID\": \"101-004-1435156-001\",\n                \"instrument\": \"EUR_USD\",\n                \"batchID\": \"2503\",\n                \"userID\": 1435156\n            }\n        }\n        >>>\n        \"\"\"\n        super(MarketOrderRequest, self).__init__()\n\n        # allowed: FOK/IOC\n        if timeInForce not in [TimeInForce.FOK,\n                               TimeInForce.IOC]:\n            raise ValueError(\"timeInForce: {}\".format(timeInForce))\n\n        # by default for a MARKET order\n        self._data.update({\"type\": OrderType.MARKET})\n        self._data.update({\"timeInForce\": timeInForce})\n\n        # required\n        self._data.update({\"instrument\": instrument})\n        self._data.update({\"units\": Units(units).value})\n\n        # optional\n        if priceBound:\n            self._data.update({\"priceBound\": PriceValue(priceBound).value})\n\n        if not hasattr(OrderPositionFill, positionFill):\n            raise ValueError(\"positionFill {}\".format(positionFill))\n\n        self._data.update({\"positionFill\": positionFill})\n\n        self._data.update({\"clientExtensions\": clientExtensions})\n        self._data.update({\"takeProfitOnFill\": takeProfitOnFill})\n        self._data.update({\"stopLossOnFill\": stopLossOnFill})\n        self._data.update({\"trailingStopLossOnFill\": trailingStopLossOnFill})\n        self._data.update({\"tradeClientExtensions\": tradeClientExtensions})\n\n    @property\n    def data(self):\n        \"\"\"data property.\n\n        return the JSON body.\n        \"\"\"\n        return dict({\"order\": super(MarketOrderRequest, self).data})\n"
  },
  {
    "path": "oandapyV20/contrib/requests/mitorder.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom .baserequest import BaseRequest\nfrom oandapyV20.types import Units, PriceValue\nfrom oandapyV20.definitions.orders import (\n    OrderType,\n    OrderPositionFill,\n    TimeInForce)\n\n\nclass MITOrderRequest(BaseRequest):\n    \"\"\"create a MarketIfTouched OrderRequest.\n\n    MITOrderRequest is used to build the body for a MITOrder.\n    The body can be used to pass to the OrderCreate endpoint.\n    \"\"\"\n\n    def __init__(self,\n                 instrument,\n                 units,\n                 price,\n                 priceBound=None,\n                 positionFill=OrderPositionFill.DEFAULT,\n                 timeInForce=TimeInForce.GTC,\n                 gtdTime=None,\n                 clientExtensions=None,\n                 takeProfitOnFill=None,\n                 stopLossOnFill=None,\n                 trailingStopLossOnFill=None,\n                 tradeClientExtensions=None):\n        \"\"\"\n        Instantiate an MITOrderRequest.\n\n        Parameters\n        ----------\n\n        instrument : string (required)\n            the instrument to create the order for\n\n        units: integer (required)\n            the number of units. If positive the order results in a LONG\n            order. If negative the order results in a SHORT order\n\n        price: float (required)\n            the price indicating the limit.\n\n        Example\n        -------\n\n        >>> import json\n        >>> from oandapyV20 import API\n        >>> import oandapyV20.endpoints.orders as orders\n        >>> from oandapyV20.contrib.requests import MITOrderRequest\n        >>>\n        >>> accountID = \"...\"\n        >>> client = API(access_token=...)\n        >>> ordr = MITOrderRequest(instrument=\"EUR_USD\",\n        ...                      units=10000, price=1.08)\n        >>> print(json.dumps(ordr.data, indent=4))\n        {\n            \"order\": {\n                \"timeInForce\": \"GTC\",\n                \"instrument\": \"EUR_USD\",\n                \"units\": \"10000\",\n                \"price\": \"1.08000\",\n                \"type\": \"MARKET_IF_TOUCHED\",\n                \"positionFill\": \"DEFAULT\"\n            }\n        }\n        >>> r = orders.OrderCreate(accountID, data=ordr.data)\n        >>> rv = client.request(r)\n        >>> ...\n        \"\"\"\n        super(MITOrderRequest, self).__init__()\n\n        # allowed: GTC/GFD/GTD\n        if timeInForce not in [TimeInForce.GTC,\n                               TimeInForce.GTD,\n                               TimeInForce.GFD]:\n            raise ValueError(\"timeInForce: {}\".format(timeInForce))\n\n        # by default for a MARKET_IF_TOUCHED order\n        self._data.update({\"type\": OrderType.MARKET_IF_TOUCHED})\n\n        # required\n        self._data.update({\"timeInForce\": timeInForce})\n        self._data.update({\"instrument\": instrument})\n        self._data.update({\"units\": Units(units).value})\n        self._data.update({\"price\": PriceValue(price).value})\n\n        # optional, but required if\n        self._data.update({\"gtdTime\": gtdTime})\n        if timeInForce == TimeInForce.GTD and not gtdTime:\n            raise ValueError(\"gtdTime missing\")\n\n        # optional\n        self._data.update({\"priceBound\": priceBound})\n        self._data.update({\"positionFill\": positionFill})\n        self._data.update({\"clientExtensions\": clientExtensions})\n        self._data.update({\"takeProfitOnFill\": takeProfitOnFill})\n        self._data.update({\"stopLossOnFill\": stopLossOnFill})\n        self._data.update({\"trailingStopLossOnFill\": trailingStopLossOnFill})\n        self._data.update({\"tradeClientExtensions\": tradeClientExtensions})\n\n    @property\n    def data(self):\n        \"\"\"data property.\n\n        return the JSON order body\n        \"\"\"\n        return dict({\"order\": super(MITOrderRequest, self).data})\n"
  },
  {
    "path": "oandapyV20/contrib/requests/onfill.py",
    "content": "# -*- coding: utf-8 -*-\nimport six\nfrom abc import ABCMeta, abstractmethod\n\nfrom .baserequest import BaseRequest\nfrom oandapyV20.types import PriceValue\nimport oandapyV20.definitions.orders as OD\n\n\n@six.add_metaclass(ABCMeta)\nclass OnFill(BaseRequest):\n    \"\"\"baseclass for onFill requests.\"\"\"\n\n    @abstractmethod\n    def __init__(self,\n                 timeInForce=OD.TimeInForce.GTC,\n                 gtdTime=None,\n                 clientExtensions=None):\n        super(OnFill, self).__init__()\n\n        if timeInForce not in [OD.TimeInForce.GTC,\n                               OD.TimeInForce.GTD,\n                               OD.TimeInForce.GFD]:\n            raise ValueError(\"timeInForce: {} invalid\".format(timeInForce))\n\n        self._data.update({\"timeInForce\": timeInForce})\n\n        # optional, but required if\n        if timeInForce == OD.TimeInForce.GTD and not gtdTime:\n            raise ValueError(\"gtdTime: value required when timeInForce is GTD\")\n        self._data.update({\"gtdTime\": gtdTime})\n        self._data.update({\"clientExtensions\": clientExtensions})\n\n\nclass TakeProfitDetails(OnFill):\n    \"\"\"Representation of the specification for a TakeProfitOrder.\n\n    It is typically used to specify 'take profit details' for the\n    'takeProfitOnFill' parameter of an OrderRequest. This way one\n    can create the Take Profit Order as a dependency when an order\n    gets filled.\n\n    The other way to create a TakeProfitOrder is to create it afterwards\n    on an existing trade. In that case you use TakeProfitOrderRequest on\n    the trade.\n    \"\"\"\n\n    def __init__(self,\n                 price,\n                 timeInForce=OD.TimeInForce.GTC,\n                 gtdTime=None,\n                 clientExtensions=None):\n        \"\"\"Instantiate TakeProfitDetails.\n\n        Parameters\n        ----------\n\n        price : float or string (required)\n            the price to trigger take profit order\n\n        timeInForce : TimeInForce (required), default TimeInForce.GTC\n            the time in force\n\n        gtdTime : DateTime (optional)\n            gtdTime is required in case timeInForce == TimeInForce.GTD\n\n        Example\n        -------\n\n        >>> import json\n        >>> from oandapyV20 import API\n        >>> import oandapyV20.endpoints.orders as orders\n        >>> from oandapyV20.contrib.requests import (\n        >>>     MarketOrderRequest, TakeProfitDetails)\n        >>>\n        >>> accountID = \"...\"\n        >>> client = API(access_token=...)\n        >>> # at time of writing EUR_USD = 1.0740\n        >>> # let us take profit at 1.10, GoodTillCancel (default)\n        >>> takeProfitOnFillOrder = TakeProfitDetails(price=1.10)\n        >>> print(takeProfitOnFillOrder.data)\n        {\n            \"timeInForce\": \"GTC\",\n            \"price\": \"1.10000\"\n        }\n        >>> ordr = MarketOrderRequest(\n        >>>     instrument=\"EUR_USD\",\n        >>>     units=10000,\n        >>>     takeProfitOnFill=takeProfitOnFillOrder.data\n        >>> )\n        >>> # or as shortcut ...\n        >>> #   takeProfitOnFill=TakeProfitDetails(price=1.10).data\n        >>> print(json.dumps(ordr.data, indent=4))\n        {\n            \"order\": {\n                \"timeInForce\": \"FOK\",\n                \"instrument\": \"EUR_USD\",\n                \"units\": \"10000\",\n                \"positionFill\": \"DEFAULT\",\n                \"type\": \"MARKET\",\n                \"takeProfitOnFill\": {\n                    \"timeInForce\": \"GTC\",\n                    \"price\": \"1.10000\"\n                }\n            }\n        }\n        >>> r = orders.OrderCreate(accountID, data=ordr.data)\n        >>> rv = client.request(r)\n        >>> ...\n        \"\"\"\n        super(TakeProfitDetails, self).__init__(\n            timeInForce=timeInForce,\n            gtdTime=gtdTime,\n            clientExtensions=clientExtensions)\n        self._data.update({\"price\": PriceValue(price).value})\n\n\nclass StopLossDetails(OnFill):\n    \"\"\"Representation of the specification for a StopLossOrder.\n\n    It is typically used to specify 'stop loss details' for the\n    'stopLossOnFill' parameter of an OrderRequest. This way one\n    can create the Stop Loss Order as a dependency when an order\n    gets filled.\n\n    The other way to create a StopLossOrder is to create it afterwards\n    on an existing trade. In that case you use StopLossOrderRequest on\n    the trade.\n    \"\"\"\n\n    def __init__(self,\n                 price,\n                 timeInForce=OD.TimeInForce.GTC,\n                 gtdTime=None,\n                 clientExtensions=None):\n        \"\"\"Instantiate StopLossDetails.\n\n        Parameters\n        ----------\n\n        price : float or string (required)\n            the price to trigger take profit order\n\n        timeInForce : TimeInForce (required), default TimeInForce.GTC\n            the time in force\n\n        gtdTime : DateTime (optional)\n            gtdTime is required in case timeInForce == TimeInForce.GTD\n\n        clientExtensions : ClientExtensions (optional)\n\n\n        Example\n        -------\n\n            >>> import json\n            >>> from oandapyV20 import API\n            >>> import oandapyV20.endpoints.orders as orders\n            >>> from oandapyV20.contrib.requests import (\n            >>>     MarketOrderRequest, StopLossDetails)\n            >>>\n            >>> accountID = \"...\"\n            >>> client = API(access_token=...)\n            >>> # at time of writing EUR_USD = 1.0740\n            >>> # let us take profit at 1.10, GoodTillCancel (default)\n            >>> stopLossOnFill = StopLossDetails(price=1.06)\n            >>> print(stopLossOnFill)\n            {\n                \"timeInForce\": \"GTC\",\n                \"price\": \"1.10000\"\n            }\n            >>> ordr = MarketOrderRequest(\n            >>>     instrument=\"EUR_USD\",\n            >>>     units=10000,\n            >>>     stopLossOnFill=stopLossOnFill.data\n            >>> )\n            >>> # or as shortcut ...\n            >>> #   stopLossOnFill=StopLossDetails(price=1.06).data\n            >>> print(json.dumps(ordr.data, indent=4))\n            >>> r = orders.OrderCreate(accountID, data=ordr.data)\n            >>> rv = client.request(r)\n            >>> ...\n        \"\"\"\n        super(StopLossDetails, self).__init__(\n            timeInForce=timeInForce,\n            gtdTime=gtdTime,\n            clientExtensions=clientExtensions)\n        self._data.update({\"price\": PriceValue(price).value})\n\n\nclass TrailingStopLossDetails(OnFill):\n    \"\"\"Representation of the specification for a TrailingStopLossOrder.\n\n    It is typically used to specify 'trailing stop loss details' for the\n    'trailingStopLossOnFill' parameter of an OrderRequest. This way one\n    can create the Trailing Stop Loss Order as a dependency when an order\n    gets filled.\n\n    The other way to create a TrailingStopLossOrder is to create it afterwards\n    on an existing trade. In that case you use TrailingStopLossOrderRequest on\n    the trade.\n    \"\"\"\n\n    def __init__(self,\n                 distance,\n                 timeInForce=OD.TimeInForce.GTC,\n                 gtdTime=None,\n                 clientExtensions=None):\n        \"\"\"Instantiate TrailingStopLossDetails.\n\n        Parameters\n        ----------\n\n        distance : float or string (required)\n            the price to trigger trailing stop loss order\n\n        timeInForce : TimeInForce (required), default TimeInForce.GTC\n            the time in force\n\n        gtdTime : DateTime (optional)\n            gtdTime is required in case timeInForce == TimeInForce.GTD\n\n        clientExtensions : ClientExtensions (optional)\n\n\n        Example\n        -------\n\n            >>> import json\n            >>> from oandapyV20 import API\n            >>> import oandapyV20.endpoints.orders as orders\n            >>> from oandapyV20.contrib.requests import (\n            >>>     MarketOrderRequest, TrailingStopLossDetails)\n            >>>\n            >>> accountID = \"...\"\n            >>> client = API(access_token=...)\n            >>> # at time of writing EUR_USD = 1.0740\n            >>> # add a trailing stoploss, at 50 pips GoodTillCancel (default)\n            >>> sld = 1.0740 - 1.0690\n            >>> trailingStopLossOnFill = TrailingStopLossDetails(distance=sld)\n            >>> print(trailingStopLossOnFill)\n            {\n                \"timeInForce\": \"GTC\",\n                \"distance\": \"0.00500\"\n            }\n            >>> ordr = MarketOrderRequest(\n            >>>     instrument=\"EUR_USD\",\n            >>>     units=10000,\n            >>>     trailingStopLossOnFill=trailingStopLossOnFill.data\n            >>> )\n            >>> print(json.dumps(ordr.data, indent=4))\n            >>> r = orders.OrderCreate(accountID, data=ordr.data)\n            >>> rv = client.request(r)\n            >>> ...\n        \"\"\"\n        super(TrailingStopLossDetails, self).__init__(\n            timeInForce=timeInForce,\n            gtdTime=gtdTime,\n            clientExtensions=clientExtensions)\n        self._data.update({\"distance\": PriceValue(distance).value})\n"
  },
  {
    "path": "oandapyV20/contrib/requests/positionclose.py",
    "content": "# -*- coding: utf-8 -*-\n\"\"\"positionclose.\"\"\"\n\nfrom .baserequest import BaseRequest\nfrom oandapyV20.types import Units\n\n\nclass PositionCloseRequest(BaseRequest):\n    \"\"\"create a PositionCloseRequest.\n\n    PositionCloseRequest is used to build the body to close a position.\n    The body can be used to pass to the PositionClose endpoint.\n    \"\"\"\n\n    def __init__(self,\n                 longUnits=None,\n                 longClientExtensions=None,\n                 shortUnits=None,\n                 shortClientExtensions=None):\n        \"\"\"\n        Instantiate a PositionCloseRequest.\n\n        Parameters\n        ----------\n\n        longUnits : integer (optional)\n            the number of long units to close\n\n        longClientExtensions : dict (optional)\n            dict representing longClientExtensions\n\n        shortUnits : integer (optional)\n            the number of short units to close\n\n        shortClientExtensions : dict (optional)\n            dict representing shortClientExtensions\n\n\n        One of the parameters or both must be supplied.\n\n        Example\n        -------\n\n        >>> import json\n        >>> from oandapyV20 import API\n        >>> import oandapyV20.endpoints.positions as positions\n        >>> from oandapyV20.contrib.requests import PositionCloseRequest\n        >>>\n        >>> accountID = \"...\"\n        >>> client = API(access_token=...)\n        >>> ordr = PositionCloseRequest(longUnits=10000)\n        >>> print(json.dumps(ordr.data, indent=4))\n        {\n           \"longUnits\": \"10000\"\n        }\n        >>> # now we have the order specification, create the order request\n        >>> r = position.PositionClose(accountID,\n        >>>                            instrument=\"EUR_USD\", data=ordr.data)\n        >>> # perform the request\n        >>> rv = client.request(r)\n        >>> print(rv)\n        >>> ...\n        \"\"\"\n        super(PositionCloseRequest, self).__init__()\n\n        if not (longUnits or shortUnits):\n            raise ValueError(\"longUnits and/or shortUnits parameter required\")\n\n        if longUnits:\n            self._data.update({\"longUnits\": Units(longUnits).value})\n\n            if longClientExtensions:\n                self._data.update({\"longClientExtensions\":\n                                   longClientExtensions})\n\n        if shortUnits:\n            self._data.update({\"shortUnits\": Units(shortUnits).value})\n\n            if shortClientExtensions:\n                self._data.update({\"shortClientExtensions\":\n                                   shortClientExtensions})\n"
  },
  {
    "path": "oandapyV20/contrib/requests/stoplossorder.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom .baserequest import BaseRequest\nfrom oandapyV20.types import TradeID, PriceValue\nfrom oandapyV20.definitions.orders import TimeInForce, OrderType\n\n\nclass StopLossOrderRequest(BaseRequest):\n    \"\"\"create a StopLossOrderRequest.\n\n    StopLossOrderRequest is used to build the body for a StopLossOrder.\n    The body can be used to pass to the OrderCreate endpoint.\n    \"\"\"\n\n    def __init__(self,\n                 tradeID,\n                 price,\n                 clientTradeID=None,\n                 timeInForce=TimeInForce.GTC,\n                 gtdTime=None,\n                 clientExtensions=None):\n        \"\"\"\n        Instantiate a StopLossOrderRequest.\n\n        Parameters\n        ----------\n\n        tradeID : string (required)\n            the tradeID of an existing trade\n\n        price : float (required)\n            the treshold price indicating the price to close the order\n\n        Example\n        -------\n\n        >>> import json\n        >>> from oandapyV20 import API\n        >>> import oandapyV20.endpoints.orders as orders\n        >>> from oandapyV20.contrib.requests import StopLossOrderRequest\n        >>>\n        >>> accountID = \"...\"\n        >>> client = API(access_token=...)\n        >>> ordr = StopLossOrderRequest(tradeID=\"1234\", price=1.07)\n        >>> print(json.dumps(ordr.data, indent=4))\n        {\n            \"order\": {\n                \"type\": \"STOP_LOSS\",\n                \"tradeID\": \"1234\",\n                \"price\": \"1.07000\",\n                \"timeInForce\": \"GTC\",\n            }\n        }\n        >>> # now we have the order specification, create the order request\n        >>> r = orders.OrderCreate(accountID, data=ordr.data)\n        >>> # perform the request\n        >>> rv = client.request(r)\n        >>> print(json.dumps(rv, indent=4))\n        >>> ...\n        \"\"\"\n        super(StopLossOrderRequest, self).__init__()\n\n        # allowed: GTC/GFD/GTD\n        if timeInForce not in [TimeInForce.GTC,\n                               TimeInForce.GTD,\n                               TimeInForce.GFD]:\n            raise ValueError(\"timeInForce: {}\".format(timeInForce))\n\n        # by default for a STOP_LOSS order\n        self._data.update({\"type\": OrderType.STOP_LOSS})\n\n        # required\n        self._data.update({\"tradeID\": TradeID(tradeID).value})\n        self._data.update({\"price\": PriceValue(price).value})\n\n        # optional\n        self._data.update({\"clientExtensions\": clientExtensions})\n        self._data.update({\"timeInForce\": timeInForce})\n        self._data.update({\"gtdTime\": gtdTime})\n\n        if timeInForce == TimeInForce.GTD and not gtdTime:\n            raise ValueError(\"gtdTime missing\")\n\n    @property\n    def data(self):\n        \"\"\"data property.\n\n        return the JSON body.\n        \"\"\"\n        return dict({\"order\": super(StopLossOrderRequest, self).data})\n"
  },
  {
    "path": "oandapyV20/contrib/requests/stoporder.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom .baserequest import BaseRequest\nfrom oandapyV20.types import Units, PriceValue\nfrom oandapyV20.definitions.orders import (\n    OrderType,\n    OrderPositionFill,\n    TimeInForce)\n\n\nclass StopOrderRequest(BaseRequest):\n    \"\"\"create a StopOrderRequest.\n\n    StopOrderRequest is used to build the body for an StopOrder.\n    The body can be used to pass to the OrderCreate endpoint.\n    \"\"\"\n\n    def __init__(self,\n                 instrument,\n                 units,\n                 price,\n                 priceBound=None,\n                 positionFill=OrderPositionFill.DEFAULT,\n                 timeInForce=TimeInForce.GTC,\n                 gtdTime=None,\n                 clientExtensions=None,\n                 takeProfitOnFill=None,\n                 stopLossOnFill=None,\n                 trailingStopLossOnFill=None,\n                 tradeClientExtensions=None):\n        \"\"\"\n        Instantiate a StopOrderRequest.\n\n        Parameters\n        ----------\n\n        instrument : string (required)\n            the instrument to create the order for\n\n        units : integer (required)\n            the number of units. If positive the order results in a LONG\n            order. If negative the order results in a SHORT order\n\n        price : float (required)\n            the treshold price indicating the price to activate the order\n\n        Example\n        -------\n\n        >>> import json\n        >>> from oandapyV20 import API\n        >>> import oandapyV20.endpoints.orders as orders\n        >>> from oandapyV20.contrib.requests import StopOrderRequest\n        >>>\n        >>> accountID = \"...\"\n        >>> client = API(access_token=...)\n        >>> ordr = StopOrderRequest(instrument=\"EUR_USD\",\n        ...                         units=10000, price=1.07)\n        >>> print(json.dumps(ordr.data, indent=4))\n        {\n            \"order\": {\n                \"type\": \"STOP\",\n                \"price\": \"1.07000\",\n                \"positionFill\": \"DEFAULT\",\n                \"instrument\": \"EUR_USD\",\n                \"timeInForce\": \"GTC\",\n                \"units\": \"10000\"\n            }\n        }\n        >>> # now we have the order specification, create the order request\n        >>> r = orders.OrderCreate(accountID, data=ordr.data)\n        >>> # perform the request\n        >>> rv = client.request(r)\n        >>> print(json.dumps(rv, indent=4))\n        >>> ...\n        \"\"\"\n        super(StopOrderRequest, self).__init__()\n\n        # by default for a STOP order\n        self._data.update({\"type\": OrderType.STOP})\n\n        # required\n        self._data.update({\"instrument\": instrument})\n        self._data.update({\"units\": Units(units).value})\n        self._data.update({\"price\": PriceValue(price).value})\n\n        # optional, but required if timeInForce.GTD\n        self._data.update({\"gtdTime\": gtdTime})\n        if timeInForce == TimeInForce.GTD and not gtdTime:\n            raise ValueError(\"gtdTime missing\")\n\n        # optional\n        self._data.update({\"timeInForce\": timeInForce})\n        self._data.update({\"priceBound\": priceBound})\n        self._data.update({\"positionFill\": positionFill})\n        self._data.update({\"clientExtensions\": clientExtensions})\n        self._data.update({\"takeProfitOnFill\": takeProfitOnFill})\n        self._data.update({\"stopLossOnFill\": stopLossOnFill})\n        self._data.update({\"trailingStopLossOnFill\": trailingStopLossOnFill})\n        self._data.update({\"tradeClientExtensions\": tradeClientExtensions})\n\n    @property\n    def data(self):\n        \"\"\"data property.\n\n        return the JSON body.\n        \"\"\"\n        return dict({\"order\": super(StopOrderRequest, self).data})\n"
  },
  {
    "path": "oandapyV20/contrib/requests/takeprofitorder.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom .baserequest import BaseRequest\nfrom oandapyV20.types import TradeID, PriceValue\nfrom oandapyV20.definitions.orders import TimeInForce, OrderType\n\n\nclass TakeProfitOrderRequest(BaseRequest):\n    \"\"\"create a TakeProfit OrderRequest.\n\n    TakeProfitOrderRequest is used to build the body for a TakeProfitOrder.\n    The body can be used to pass to the OrderCreate endpoint.\n    \"\"\"\n\n    def __init__(self,\n                 tradeID,\n                 price,\n                 clientTradeID=None,\n                 timeInForce=TimeInForce.GTC,\n                 gtdTime=None,\n                 clientExtensions=None):\n        \"\"\"\n        Instantiate a TakeProfitOrderRequest.\n\n        Parameters\n        ----------\n\n        tradeID : string (required)\n            the tradeID of an existing trade\n\n        price: float (required)\n            the price indicating the target price to close the order.\n\n        Example\n        -------\n\n        >>> import json\n        >>> from oandapyV20 import API\n        >>> import oandapyV20.endpoints.orders as orders\n        >>> from oandapyV20.contrib.requests import TakeProfitOrderRequest\n        >>>\n        >>> accountID = \"...\"\n        >>> client = API(access_token=...)\n        >>> ordr = TakeProfitOrderRequest(tradeID=\"1234\",\n        >>>                               price=1.22)\n        >>> print(json.dumps(ordr.data, indent=4))\n        {\n            \"order\": {\n                \"timeInForce\": \"GTC\",\n                \"price\": \"1.22000\",\n                \"type\": \"TAKE_PROFIT\",\n                \"tradeID\": \"1234\"\n            }\n        }\n        >>> r = orders.OrderCreate(accountID, data=ordr.data)\n        >>> rv = client.request(r)\n        >>> ...\n        \"\"\"\n        super(TakeProfitOrderRequest, self).__init__()\n\n        # allowed: GTC/GFD/GTD\n        if timeInForce not in [TimeInForce.GTC,\n                               TimeInForce.GTD,\n                               TimeInForce.GFD]:\n            raise ValueError(\"timeInForce: {}\".format(timeInForce))\n\n        # by default for a TAKE_PROFIT order\n        self._data.update({\"type\": OrderType.TAKE_PROFIT})\n        self._data.update({\"timeInForce\": timeInForce})\n\n        # required\n        self._data.update({\"tradeID\": TradeID(tradeID).value})\n        self._data.update({\"price\": PriceValue(price).value})\n\n        # optional, but required if\n        self._data.update({\"gtdTime\": gtdTime})\n        if timeInForce == TimeInForce.GTD and not gtdTime:\n            raise ValueError(\"gtdTime missing\")\n\n        # optional\n        self._data.update({\"clientExtensions\": clientExtensions})\n\n    @property\n    def data(self):\n        \"\"\"data property.\n\n        return the JSON order body\n        \"\"\"\n        return dict({\"order\": super(TakeProfitOrderRequest, self).data})\n"
  },
  {
    "path": "oandapyV20/contrib/requests/tradeclose.py",
    "content": "# -*- coding: utf-8 -*-\n\"\"\"tradeclose.\"\"\"\n\nfrom .baserequest import BaseRequest\n\n\nclass TradeCloseRequest(BaseRequest):\n    \"\"\"create a TradeCloseRequest.\n\n    TradeCloseRequest is used to build the body to close a trade.\n    The body can be used to pass to the TradeClose endpoint.\n    \"\"\"\n\n    def __init__(self, units=\"ALL\"):\n        \"\"\"\n        Instantiate a TradeCloseRequest.\n\n        Parameters\n        ----------\n\n        units : integer (optional)\n            the number of units to close. Default it is set to \"ALL\".\n\n        Example\n        -------\n\n        >>> import json\n        >>> from oandapyV20 import API\n        >>> import oandapyV20.endpoints.trades as trades\n        >>> from oandapyV20.contrib.requests import TradeCloseRequest\n        >>>\n        >>> accountID = \"...\"\n        >>> client = API(access_token=...)\n        >>> ordr = TradeCloseRequest(units=10000)\n        >>> print(json.dumps(ordr.data, indent=4))\n        {\n           \"units\": \"10000\"\n        }\n        >>> # now we have the order specification, create the order request\n        >>> r = trades.TradeClose(accountID, tradeID=1234,\n        >>>                       data=ordr.data)\n        >>> # perform the request\n        >>> rv = client.request(r)\n        >>> print(rv)\n        >>> ...\n        \"\"\"\n        super(TradeCloseRequest, self).__init__()\n\n        # by default for a TradeClose no parameters are required\n        if units:\n            self._data.update(\n                {\"units\":\n                 \"{:d}\".format(int(units)) if units != \"ALL\" else \"ALL\"})\n"
  },
  {
    "path": "oandapyV20/contrib/requests/trailingstoplossorder.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom .baserequest import BaseRequest\nfrom oandapyV20.types import TradeID, PriceValue\nfrom oandapyV20.definitions.orders import TimeInForce, OrderType\n\n\nclass TrailingStopLossOrderRequest(BaseRequest):\n    \"\"\"create a TrailingStopLossOrderRequest.\n\n    TrailingStopLossOrderRequest is used to build the body for a\n    TrailingStopLossOrder. The body can be used to pass to the\n    OrderCreate endpoint.\n    \"\"\"\n\n    def __init__(self,\n                 tradeID,\n                 distance,\n                 clientTradeID=None,\n                 timeInForce=TimeInForce.GTC,\n                 gtdTime=None,\n                 clientExtensions=None):\n        \"\"\"\n        Instantiate a TrailingStopLossOrderRequest.\n\n        Parameters\n        ----------\n\n        tradeID : string (required)\n            the tradeID of an existing trade\n\n        distance : float (required)\n            the price distance\n\n        Example\n        -------\n\n        >>> import json\n        >>> from oandapyV20 import API\n        >>> import oandapyV20.endpoints.orders as orders\n        >>> from oandapyV20.contrib.requests import TrailingStopLossOrderRequest\n        >>>\n        >>> accountID = \"...\"\n        >>> client = API(access_token=...)\n        >>> ordr = TrailingStopLossOrderRequest(tradeID=\"1234\", distance=20)\n        >>> print(json.dumps(ordr.data, indent=4))\n        {\n            \"order\": {\n                \"type\": \"TRAILING_STOP_LOSS\",\n                \"tradeID\": \"1234\",\n                \"timeInForce\": \"GTC\",\n                \"distance\": \"20.00000\"\n            }\n        }\n        >>> # now we have the order specification, create the order request\n        >>> r = orders.OrderCreate(accountID, data=ordr.data)\n        >>> # perform the request\n        >>> rv = client.request(r)\n        >>> print(json.dumps(rv, indent=4))\n        >>> ...\n        \"\"\"\n        super(TrailingStopLossOrderRequest, self).__init__()\n\n        # allowed: GTC/GFD/GTD\n        if timeInForce not in [TimeInForce.GTC,\n                               TimeInForce.GTD,\n                               TimeInForce.GFD]:\n            raise ValueError(\"timeInForce: {}\".format(timeInForce))\n\n        # by default for a TRAILING_STOP_LOSS order\n        self._data.update({\"type\": OrderType.TRAILING_STOP_LOSS})\n\n        # required\n        self._data.update({\"tradeID\": TradeID(tradeID).value})\n        self._data.update({\"distance\": PriceValue(distance).value})\n\n        # optional\n        self._data.update({\"clientExtensions\": clientExtensions})\n        self._data.update({\"timeInForce\": timeInForce})\n        self._data.update({\"gtdTime\": gtdTime})\n\n        if timeInForce == TimeInForce.GTD and not gtdTime:\n            raise ValueError(\"gtdTime missing\")\n\n    @property\n    def data(self):\n        \"\"\"data property.\n\n        return the JSON body.\n        \"\"\"\n        return dict({\"order\": super(TrailingStopLossOrderRequest, self).data})\n"
  },
  {
    "path": "oandapyV20/definitions/__init__.py",
    "content": "# -*- coding: utf-8 -*-\n\"\"\"dynamically add the classes for definition representations.\n\nMost of the endpoint groups have some definitions that apply. These are\nin the definitions package. It is conveniant to have access by a class\nrepresenting a specific group of definitions instead of a dictionary.\n\"\"\"\nimport sys\nfrom importlib import import_module\nimport six\n\n\ndyndoc = \"\"\"Definition representation of {cls}\n\n    Definitions used in requests and responses. This\n    class provides the ID and the description of the definitions.\n\n    >>> import {PTH} as def{mod}\n    >>> print def{mod}.{cls}.{firstItem}\n    {orig}\n    >>> c = def{mod}.{cls}()\n    >>> print c[c.{firstItem}]\n    {firstItemVal}\n    >>> # or\n    >>> print def{mod}.{cls}().definitions[c.{firstItem}]\n    >>> # all keys\n    >>> print def{mod}.{cls}().definitions.keys()\n    >>> ...\n\n\"\"\"\n\n_doc = \"\"\"\n    .. note::\n\n       attribute name *{}* is renamed to *{}*, value stil is *{}*. This\n       means that a lookup stil applies.\n\"\"\"\n\n\ndef make_definition_classes(mod):\n    \"\"\"Dynamically create the definition classes from module 'mod'.\"\"\"\n    rootpath = \"oandapyV20\"\n    PTH = \"{}.definitions.{}\".format(rootpath, mod)\n\n    M = import_module(PTH)\n    __ALL__ = []  # construct the __all__ variable\n    for cls, cldef in M.definitions.items():\n\n        orig, fiV = next(six.iteritems(cldef))\n        fiK = orig.replace('-', '_')\n        # create the docstring dynamically\n        clsdoc = dyndoc.format(cls=cls,\n                               PTH=PTH,\n                               mod=mod,\n                               firstItem=fiK, orig=orig,\n                               firstItemVal=fiV)\n\n        # Since we can't change the docstring afterwards (it's readonly)\n        # figure this out before and not during ...\n        for K, V in cldef.items():\n            attrName = K\n            if \"-\" in K:\n                attrName = K.replace('-', '_')\n                adoc = _doc.format(K, attrName, K)\n                clsdoc += adoc\n\n        # the class\n        dyncls = type(cls, (object,), {'__doc__': clsdoc})\n\n        definitions = dict()\n        for K, V in cldef.items():\n            attrName = K\n            if \"-\" in K:\n                attrName = K.replace('-', '_')\n            setattr(dyncls, attrName, K)  # set as class attributes\n            definitions.update({K: V})    # for mapping by __getitem__\n\n        def mkgi():\n            def __getitem__(self, definitionID):\n                \"\"\"return description for definitionID.\"\"\"\n                return self._definitions[definitionID]\n            return __getitem__\n\n        def mkinit(definitions):\n            def __init__(self):\n                self._definitions = definitions\n\n            return __init__\n\n        def mkPropDefinitions():\n            def definitions(self):\n                \"\"\"readonly property holding definition dict.\"\"\"\n                return self._definitions\n            return property(definitions)\n\n        setattr(dyncls, \"__getitem__\", mkgi())\n        setattr(dyncls, \"__init__\", mkinit(definitions))\n        setattr(dyncls, \"definitions\", mkPropDefinitions())\n        setattr(sys.modules[\"{}.definitions.{}\".format(rootpath, mod)],\n                cls, dyncls)\n        __ALL__.append(cls)\n\n    setattr(sys.modules[\"{}.definitions.{}\".format(rootpath, mod)],\n            \"__all__\", tuple(__ALL__))\n\n\ndefinitionModules = [\n    'accounts',\n    'instruments',\n    'orders',\n    'pricing',\n    'primitives',\n    'trades',\n    'transactions'\n]\n\n# dynamically create all the definition classes from the modules\nfor M in definitionModules:\n    make_definition_classes(M)\n"
  },
  {
    "path": "oandapyV20/definitions/accounts.py",
    "content": "# -*- coding: utf-8 -*-\n\"\"\"Account Definitions.\"\"\"\n\ndefinitions = {\n    \"GuaranteedStopLossOrderMode\": {\n        \"DISABLED\": \"The account is not permitted to create guaranteed \"\n                    \"Stop Loss Orders.\",\n        \"ALLOWED\": \"The account is able, but not required to have guaranteed \"\n                    \"Stop Loss Orders for open Trades.\",\n        \"REQUIRED\": \"The account is required to have guaranteed \"\n                    \"Stop Loss Orders for open Trades.\",\n    },\n    \"AccountFinancingMode\": {\n        \"NO_FINANCING\": \"No financing is paid/charged for open Trades \"\n                        \"in the Account\",\n        \"SECOND_BY_SECOND\": \"Second-by-second financing is paid/charged \"\n                            \"for open Trades in the Account, both daily \"\n                            \"and when the the Trade is closed\",\n        \"DAILY\": \"A full day’s worth of financing is paid/charged for \"\n                 \"open Trades in the Account daily at 5pm New York time\"\n    },\n    \"PositionAggregationMode\": {\n        \"ABSOLUTE_SUM\": \"The Position value or margin for each side (long and\"\n                        \" short) of the Position are computed independently \"\n                        \"and added together.\",\n        \"MAXIMAL_SIDE\": \"The Position value or margin for each side (long and\"\n                        \" short) of the Position are computed independently. \"\n                        \"The Position value or margin chosen is the maximal \"\n                        \"absolute value of the two.\",\n        \"NET_SUM\": \"The units for each side (long and short) of the Position \"\n                   \"are netted together and the resulting value (long or \"\n                   \"short) is used to compute the Position value or margin.\"\n    }\n}\n"
  },
  {
    "path": "oandapyV20/definitions/instruments.py",
    "content": "# -*- coding: utf-8 -*-\n\"\"\"Instruments Definitions.\"\"\"\n\ndefinitions = {\n    \"PriceComponents\": {\n        \"A\": \"Ask\",\n        \"B\": \"Bid\",\n        \"M\": \"Mid\",\n    },\n    \"CandlestickGranularity\": {\n        \"S5\": \"5 second candlesticks, minute alignment\",\n        \"S10\": \"10 second candlesticks, minute alignment\",\n        \"S15\": \"15 second candlesticks, minute alignment\",\n        \"S30\": \"30 second candlesticks, minute alignment\",\n        \"M1\": \"1 minute candlesticks, minute alignment\",\n        \"M2\": \"2 minute candlesticks, hour alignment\",\n        \"M4\": \"4 minute candlesticks, hour alignment\",\n        \"M5\": \"5 minute candlesticks, hour alignment\",\n        \"M10\": \"10 minute candlesticks, hour alignment\",\n        \"M15\": \"15 minute candlesticks, hour alignment\",\n        \"M30\": \"30 minute candlesticks, hour alignment\",\n        \"H1\": \"1 hour candlesticks, hour alignment\",\n        \"H2\": \"1 hour candlesticks, day alignment\",\n        \"H3\": \"3 hour candlesticks, day alignment\",\n        \"H4\": \"4 hour candlesticks, day alignment\",\n        \"H6\": \"6 hour candlesticks, day alignment\",\n        \"H8\": \"8 hour candlesticks, day alignment\",\n        \"H12\": \"12 hour candlesticks, day alignment\",\n        \"D\": \"1 day candlesticks, day alignment\",\n        \"W\": \"1 week candlesticks, aligned to start of week\",\n        \"M\": \"1 month candlesticks, aligned to first day of the month\",\n    },\n    \"WeeklyAlignment\": {\n        \"Monday\": \"Monday\",\n        \"Tuesday\": \"Tuesday\",\n        \"Wednesday\": \"Wednesday\",\n        \"Thursday\": \"Thursday\",\n        \"Friday\": \"Friday\",\n        \"Saturday\": \"Saturday\",\n        \"Sunday\": \"Sunday\",\n    },\n}\n"
  },
  {
    "path": "oandapyV20/definitions/orders.py",
    "content": "# -*- coding: utf-8 -*-\n\"\"\"Order related definitions.\"\"\"\n\ndefinitions = {\n    \"OrderType\": {\n        \"MARKET\": \"A Market Order\",\n        \"LIMIT\": \"A Limit Order\",\n        \"STOP\": \"A Stop Order\",\n        \"MARKET_IF_TOUCHED\": \"A Market-if-touched Order\",\n        \"TAKE_PROFIT\": \"A Take Profit Order\",\n        \"STOP_LOSS\": \"A Stop Loss Order\",\n        \"TRAILING_STOP_LOSS\": \"A Trailing Stop Loss Order\",\n        \"FIXED_PRICE\": \"A Fixed Price Order\"\n    },\n    \"CancellableOrderType\": {\n        \"LIMIT\": \"A Limit Order\",\n        \"STOP\": \"A Stop Order\",\n        \"MARKET_IF_TOUCHED\": \"A Market-if-touched Order\",\n        \"TAKE_PROFIT\": \"A Take Profit Order\",\n        \"STOP_LOSS\": \"A Stop Loss Order\",\n        \"TRAILING_STOP_LOSS\": \"A Trailing Stop Loss Order\",\n    },\n    \"OrderState\": {\n        \"PENDING\": \"The Order is currently pending execution\",\n        \"FILLED\": \"The Order has been filled\",\n        \"TRIGGERED\": \"The Order has been triggered\",\n        \"CANCELLED\": \"The Order has been cancelled\",\n    },\n    \"OrderStateFilter\": {\n        \"PENDING\": \"The orders that are currently pending execution\",\n        \"FILLED\": \"The orders that have been filled\",\n        \"TRIGGERED\": \"The orders that have been triggered\",\n        \"CANCELLED\": \"The orders that have been cancelled\",\n        \"ALL\": \"The orders that are in any of the possible states: \"\n               \"PENDING, FILLED, TRIGGERED, CANCELLED\",\n    },\n    \"TimeInForce\": {\n        \"GTC\": \"The Order is “Good unTil Cancelled”\",\n        \"GTD\": \"The Order is “Good unTil Date” and will be cancelled at \"\n               \"the provided time\",\n        \"GFD\": \"The Order is “Good for Day” and will be cancelled at \"\n               \"5pm New York time\",\n        \"FOK\": \"The Order must be immediately “Filled Or Killed”\",\n        \"IOC\": \"The Order must be “Immediately partially filled Or Killed”\",\n    },\n    \"OrderPositionFill\": {\n        \"OPEN_ONLY\": \"When the Order is filled, only allow Positions to be \"\n                     \"opened or extended.\",\n        \"REDUCE_FIRST\": \"When the Order is filled, always fully reduce an \"\n                        \"existing Position before opening a new Position.\",\n        \"REDUCE_ONLY\": \"When the Order is filled, only reduce an existing \"\n                       \"Position.\",\n        \"DEFAULT\": \"When the Order is filled, use REDUCE_FIRST behaviour \"\n                   \"for non-client hedging Accounts, and OPEN_ONLY behaviour \"\n                   \"for client hedging Accounts.\"\n    },\n    \"OrderTriggerCondition\": {\n        \"DEFAULT\": \"Trigger an Order the “natural” way: compare its price to \"\n                   \"the ask for long Orders and bid for short Orders\",\n        \"INVERSE\": \"Trigger an Order the opposite of the “natural” way: \"\n                   \"compare its price the bid for long Orders and ask for \"\n                   \"short Orders.\",\n        \"BID\": \"Trigger an Order by comparing its price to the bid regardless\"\n               \" of whether it is long or short.\",\n        \"ASK\": \"Trigger an Order by comparing its price to the ask regardless\"\n               \" of whether it is long or short.\",\n        \"MID\": \"Trigger an Order by comparing its price to the midpoint \"\n               \"regardless of whether it is long or short.\"\n    }\n}\n"
  },
  {
    "path": "oandapyV20/definitions/pricing.py",
    "content": "# -*- coding: utf-8 -*-\n\"\"\"Pricing related Definitions.\"\"\"\n\ndefinitions = {\n    \"PriceStatus\": {\n        \"tradeable\": \"The Instrument’s price is tradeable.\",\n        \"non-tradeable\": \"The Instrument’s price is not tradeable.\",\n        \"invalid\": \"The Instrument of the price is invalid or there \"\n                   \"is no valid Price for the Instrument.\"\n    },\n}\n"
  },
  {
    "path": "oandapyV20/definitions/primitives.py",
    "content": "# -*- coding: utf-8 -*-\n\"\"\"Primitives definitions.\"\"\"\n\ndefinitions = {\n    \"InstrumentType\": {\n        \"CURRENCY\": \"Currency\",\n        \"CFD\": \"Contract For Difference\",\n        \"METAL\": \"Metal\"\n    },\n    \"AcceptDatetimeFormat\": {\n        \"UNIX\": \"Unix timeformat: DateTime fields will be specified \"\n                \"or returned in the “12345678.000000123” format.\",\n        \"RFC3339\": \"RFC3339 timeformat: DateTime will be specified \"\n                \"or returned in “YYYY-MM-DDTHH:MM:SS.nnnnnnnnnZ” format.\"\n    },\n    \"Direction\": {\n       \"LONG\": \"A long Order is used to to buy units of an Instrument. A \"\n               \"Trade is long when it has bought units of an Instrument.\",\n       \"SHORT\": \"A short Order is used to to sell units of an Instrument. A \"\n                \"Trade is short when it has sold units of an Instrument\"\n    }\n}\n"
  },
  {
    "path": "oandapyV20/definitions/trades.py",
    "content": "# -*- coding: utf-8 -*-\n\"\"\"Trades definitions.\"\"\"\n\ndefinitions = {\n    \"TradeState\": {\n        \"OPEN\": \"The Trade is currently open\",\n        \"CLOSED\": \"The Trade has been fully closed\",\n        \"CLOSE_WHEN_TRADABLE\": \"The Trade will be closed as soon as the \"\n                               \"trade’s instrument becomes tradeable\"\n    },\n    \"TradeStateFilter\": {\n        \"OPEN\": \"The Trades that are currently open\",\n        \"CLOSED\": \"The Trades that have been fully closed\",\n        \"CLOSE_WHEN_TRADEABLE\": \"The Trades that will be closed as soon as \"\n                                \"the trades' instrument becomes tradeable\",\n        \"ALL\": \"The Trades that are in any of the possible states listed \"\n               \"above.\"\n    },\n    \"TradePL\": {\n        \"POSITIVE\": \"An open Trade currently has a positive (profitable) \"\n                    \"unrealized P/L, or a closed Trade realized a positive \"\n                    \"amount of P/L.\",\n        \"NEGATIVE\": \"An open Trade currently has a negative (losing) \"\n                    \"unrealized P/L, or a closed Trade realized a negative \"\n                    \"amount of P/L\",\n        \"ZERO\": \"An open Trade currently has unrealized P/L of zero \"\n                \"(neither profitable nor losing), or a closed Trade realized \"\n                \"a P/L amount of zero.\"\n    }\n}\n"
  },
  {
    "path": "oandapyV20/definitions/transactions.py",
    "content": "# -*- coding: utf-8 -*-\n\"\"\"Transactions definitions.\"\"\"\n\ndefinitions = {\n    \"TransactionType\": {\n        \"CREATE\": \"Account Create Transaction\",\n        \"CLOSE\": \"Account Close Transaction\",\n        \"REOPEN\": \"Account Reopen Transaction\",\n        \"CLIENT_CONFIGURE\": \"Client Configuration Transaction\",\n        \"CLIENT_CONFIGURE_REJECT\": \"Client Configuration Reject Transaction\",\n        \"TRANSFER_FUNDS\": \"Transfer Funds Transaction\",\n        \"TRANSFER_FUNDS_REJECT\": \"Transfer Funds Reject Transaction\",\n        \"MARKET_ORDER\": \"Market Order Transaction\",\n        \"MARKET_ORDER_REJECT\": \"Market Order Reject Transaction\",\n        \"FIXED_PRICE_ORDER\": \"Fixed Price Order Transaction\",\n        \"LIMIT_ORDER\": \"Limit Order Transaction\",\n        \"LIMIT_ORDER_REJECT\": \"Limit Order Reject Transaction\",\n        \"STOP_ORDER\": \"Stop Order Transaction\",\n        \"STOP_ORDER_REJECT\": \"Stop Order Reject Transaction\",\n        \"MARKET_IF_TOUCHED_ORDER\": \"Market if Touched Order Transaction\",\n        \"MARKET_IF_TOUCHED_ORDER_REJECT\": \"Market if Touched Order \"\n                                          \"Reject Transaction\",\n        \"TAKE_PROFIT_ORDER\": \"Take Profit Order Transaction\",\n        \"TAKE_PROFIT_ORDER_REJECT\": \"Take Profit Order Reject Transaction\",\n        \"STOP_LOSS_ORDER\": \"Stop Loss Order Transaction\",\n        \"STOP_LOSS_ORDER_REJECT\": \"Stop Loss Order Reject Transaction\",\n        \"TRAILING_STOP_LOSS_ORDER\": \"Trailing Stop Loss Order Transaction\",\n        \"TRAILING_STOP_LOSS_ORDER_REJECT\": \"Trailing Stop Loss Order \"\n                                           \"Reject Transaction\",\n        \"ORDER_FILL\": \"Order Fill Transaction\",\n        \"ORDER_CANCEL\": \"Order Cancel Transaction\",\n        \"ORDER_CANCEL_REJECT\": \"Order Cancel Reject Transaction\",\n        \"ORDER_CLIENT_EXTENSIONS_MODIFY\": \"Order Client Extensions \"\n                                          \"Modify Transaction\",\n        \"ORDER_CLIENT_EXTENSIONS_MODIFY_REJECT\": \"Order Client Extensions \"\n                                          \"Modify Reject Transaction\",\n        \"TRADE_CLIENT_EXTENSIONS_MODIFY\": \"Trade Client Extensions \"\n                                          \"Modify Transaction\",\n        \"TRADE_CLIENT_EXTENSIONS_MODIFY_REJECT\": \"Trade Client Extensions \"\n                                                 \"Modify Reject Transaction\",\n        \"MARGIN_CALL_ENTER\": \"Margin Call Enter Transaction\",\n        \"MARGIN_CALL_EXTEND\": \"Margin Call Extend Transaction\",\n        \"MARGIN_CALL_EXIT\": \"Margin Call Exit Transaction\",\n        \"DELAYED_TRADE_CLOSURE\": \"Delayed Trade Closure Transaction\",\n        \"DAILY_FINANCING\": \"Daily Financing Transaction\",\n        \"RESET_RESETTABLE_PL\": \"Reset Resettable PL Transaction\",\n    },\n    \"FundingReason\": {\n        \"CLIENT_FUNDING\": \"The client has initiated a funds transfer\",\n        \"ACCOUNT_TRANSFER\": \"Funds are being transfered between \"\n                            \"two Accounts.\",\n        \"DIVISION_MIGRATION\": \"Funds are being transfered as part of a \"\n                              \"Division migration\",\n        \"SITE_MIGRATION\": \"Funds are being transfered as part of a \"\n                          \"Site migration\",\n        \"ADJUSTMENT\": \"Funds are being transfered as part of an \"\n                      \"Account adjustment\"\n    },\n    \"MarketOrderReason\": {\n        \"CLIENT_ORDER\": \"The Market Order was created at the request \"\n                        \"of a client\",\n        \"TRADE_CLOSE\": \"The Market Order was created to close a Trade \"\n                       \"at the request of a client\",\n        \"POSITION_CLOSEOUT\": \"The Market Order was created to close a \"\n                             \"Position at the request of a client\",\n        \"MARGIN_CLOSEOUT\": \"The Market Order was created as part of a \"\n                           \"Margin Closeout\",\n        \"DELAYED_TRADE_CLOSE\": \"The Market Order was created to close a \"\n                               \"trade marked for delayed closure\",\n    },\n    \"FixedPriceOrderReason\": {\n        \"PLATFORM_ACCOUNT_MIGRATION\": \"The Fixed Price Order was created as \"\n                                      \"part of a platform account migration\",\n    },\n    \"LimitOrderReason\": {\n        \"CLIENT_ORDER\": \"The Limit Order was initiated at the request of a \"\n                        \"client\",\n        \"REPLACEMENT\": \"The Limit Order was initiated as a replacement for \"\n                       \"an existing Order\",\n    },\n    \"StopOrderReason\": {\n        \"CLIENT_ORDER\": \"The Stop Order was initiated at the request of a \"\n                        \"client\",\n        \"REPLACEMENT\": \"The Stop Order was initiated as a replacement for \"\n                       \"an existing Order\",\n    },\n    \"MarketIfTouchedOrderReason\": {\n        \"CLIENT_ORDER\": \"The Market-if-touched Order was initiated at the \"\n                        \"request of a client\",\n        \"REPLACEMENT\": \"The Market-if-touched Order was initiated as a \"\n                       \"replacement for an existing Order\",\n    },\n    \"TakeProfitOrderReason\": {\n        \"CLIENT_ORDER\": \"The Take Profit Order was initiated at the request \"\n                        \"of a client\",\n        \"REPLACEMENT\": \"The Take Profit Order was initiated as a replacement \"\n                       \"for an existing Order\",\n        \"ON_FILL\": \"The Take Profit Order was initiated automatically when \"\n                   \"an Order was filled that opened a new Trade requiring \"\n                   \"a Take Profit Order.\",\n    },\n    \"StopLossOrderReason\": {\n        \"CLIENT_ORDER\": \"The Stop Loss Order was initiated at the request \"\n                        \"of a client\",\n        \"REPLACEMENT\": \"The Stop Loss Order was initiated as a replacement \"\n                       \"for an existing Order\",\n        \"ON_FILL\": \"The Stop Loss Order was initiated automatically when \"\n                   \"an Order was filled that opened a new Trade requiring \"\n                   \"a Stop Loss Order.\",\n    },\n    \"TrailingStopLossOrderReason\": {\n        \"CLIENT_ORDER\": \"The Trailing Stop Loss Order was initiated at the \"\n                        \"request of a client\",\n        \"REPLACEMENT\": \"The Trailing Stop Loss Order was initiated as a \"\n                       \"replacement for an existing Order\",\n        \"ON_FILL\": \"The Trailing Stop Loss Order was initiated automatically \"\n                   \"when an Order was filled that opened a new Trade \"\n                   \"requiring a Trailing Stop Loss Order.\",\n    },\n    \"OrderFillReason\": {\n        \"LIMIT_ORDER\": \"The Order filled was a Limit Order\",\n        \"STOP_ORDER\": \"The Order filled was a Stop Order\",\n        \"MARKET_IF_TOUCHED_ORDER\": \"The Order filled was a \"\n                                   \"Market-if-touched Order\",\n        \"TAKE_PROFIT_ORDER\": \"The Order filled was a Take Profit Order\",\n        \"STOP_LOSS_ORDER\": \"The Order filled was a Stop Loss Order\",\n        \"TRAILING_STOP_LOSS_ORDER\": \"The Order filled was a Trailing Stop \"\n                                    \"Loss Order\",\n        \"MARKET_ORDER\": \"The Order filled was a Market Order\",\n        \"MARKET_ORDER_TRADE_CLOSE\": \"The Order filled was a Market Order \"\n                                    \"used to explicitly close a Trade\",\n        \"MARKET_ORDER_POSITION_CLOSEOUT\": \"The Order filled was a Market \"\n                                          \"Order used to explicitly close \"\n                                          \"a Position\",\n        \"MARKET_ORDER_MARGIN_CLOSEOUT\": \"The Order filled was a Market Order \"\n                                        \"used for a Margin Closeout\",\n        \"MARKET_ORDER_DELAYED_TRADE_CLOSE\": \"The Order filled was a Market \"\n                                            \"Order used for a delayed Trade \"\n                                            \"close\",\n    },\n    \"OrderCancelReason\": {\n        \"INTERNAL_SERVER_ERROR\": \"The Order was cancelled because at the\"\n                                 \"time of filling, an unexpected internal \"\n                                 \"server error occurred.\",\n        \"ACCOUNT_LOCKED\": \"The Order was cancelled because at the time of \"\n                          \"filling the account was locked.\",\n        \"ACCOUNT_NEW_POSITIONS_LOCKED\": \"The order was to be filled, \"\n                                        \"however the account is configured \"\n                                        \"to not allow new positions to be \"\n                                        \"created.\",\n        \"ACCOUNT_ORDER_CREATION_LOCKED\": \"Filling the Order wasn’t possible \"\n                                         \"because it required the creation \"\n                                         \"of a dependent Order and the \"\n                                         \"Account is locked for Order \"\n                                         \"creation.\",\n        \"ACCOUNT_ORDER_FILL_LOCKED\": \"Filling the Order was not possible \"\n                                     \"because the Account is locked for \"\n                                     \"filling Orders.\",\n        \"CLIENT_REQUEST\": \"The Order was cancelled explicitly at the request \"\n                          \"of the client.\",\n        \"MIGRATION\": \"The Order cancelled because it is being migrated to \"\n                     \"another account.\",\n        \"MARKET_HALTED\": \"Filling the Order wasn’t possible because the \"\n                         \"Order’s instrument was halted.\",\n        \"LINKED_TRADE_CLOSED\": \"The Order is linked to an open Trade that \"\n                               \"was closed.\",\n        \"TIME_IN_FORCE_EXPIRED\": \"The time in force specified for this order \"\n                                 \"has passed.\",\n        \"INSUFFICIENT_MARGIN\": \"Filling the Order wasn’t possible because \"\n                               \"the Account had insufficient margin.\",\n        \"FIFO_VIOLATION\": \"Filling the Order would have resulted in a FIFO \"\n                          \"violation.\",\n        \"BOUNDS_VIOLATION\": \"Filling the Order would have violated the \"\n                            \"Order’s price bound.\",\n        \"CLIENT_REQUEST_REPLACED\": \"The Order was cancelled for replacement \"\n                                   \"at the request of the client.\",\n        \"INSUFFICIENT_LIQUIDITY\": \"Filling the Order wasn’t possible \"\n                                  \"because enough liquidity available.\",\n        \"TAKE_PROFIT_ON_FILL_GTD_TIMESTAMP_IN_PAST\":\n            \"Filling the Order would have resulted in the creation \"\n            \"of a Take Profit Order with a GTD time in the past.\",\n        \"TAKE_PROFIT_ON_FILL_LOSS\":\n            \"Filling the Order would result in the creation of a \"\n            \"Take Profit Order that would have been filled immediately, \"\n            \"closing the new Trade at a loss.\",\n        \"LOSING_TAKE_PROFIT\":\n            \"Filling the Order would result in the creation of a \"\n            \"Take Profit Loss Order that would close the new Trade \"\n            \"at a loss when filled.\",\n        \"STOP_LOSS_ON_FILL_GTD_TIMESTAMP_IN_PAST\":\n            \"Filling the Order would have resulted in the creation of a \"\n            \"Stop Loss Order with a GTD time in the past.\",\n        \"STOP_LOSS_ON_FILL_LOSS\":\n            \"Filling the Order would result in the creation of a \"\n            \"Stop Loss Order that would have been filled immediately, \"\n            \"closing the new Trade at a loss.\",\n        \"STOP_LOSS_ON_FILL_PRICE_DISTANCE_MAXIMUM_EXCEEDED\":\n            \"Filling the Order would result in the creation of a Stop Loss \"\n            \"Order whose price would be zero or negative due to the \"\n            \"specified distance.\",\n        \"STOP_LOSS_ON_FILL_REQUIRED\":\n            \"Filling the Order would not result in the creation of Stop \"\n            \"Loss Order, however the Account’s configuration requires that \"\n            \"all Trades have a Stop Loss Order attached to them\",\n        \"STOP_LOSS_ON_FILL_GUARANTEED_REQUIRED\":\n            \"Filling the Order would not result in the creation of a \"\n            \"guaranteed Stop Loss Order, however the Account’s configuration \"\n            \"requires that all Trades have a guaranteed Stop Loss Order \"\n            \"attached to them\",\n        \"STOP_LOSS_ON_FILL_GUARANTEED_NOT_ALLOWED\":\n            \"Filling the Order would result in the creation of a guaranteed \"\n            \"Stop Loss Order, however the Account’s configuration does not \"\n            \"allow guaranteed Stop Loss Orders\",\n        \"STOP_LOSS_ON_FILL_GUARANTEED_MINIMUM_DISTANCE_NOT_MET\":\n            \"Filling the Order would result in the creation of a guaranteed \"\n            \"Stop Loss Order with a distance smaller than the configured \"\n            \"mininum distance.\",\n        \"STOP_LOSS_ON_FILL_GUARANTEED_LEVEL_RESTRICTION_EXCEEDED\":\n            \"Filling the Order would result in the creation of a guaranteed \"\n            \"Stop Loss Order with trigger price and number of units that \"\n            \"that violates the account’s guaranteed Stop Loss Order level \"\n            \"restriction\",\n        \"STOP_LOSS_ON_FILL_GUARANTEED_HEDGING_NOT_ALLOWED\":\n            \"Filling the Order would result in the creation of a guaranteed \"\n            \"Stop Loss Order for a hedged Trade, however the Account’s \"\n            \"configuration does not allow guaranteed Stop Loss Orders for \"\n            \"hedged Trades/Positions.\",\n        \"STOP_LOSS_ON_FILL_TIME_IN_FORCE_INVALID\":\n            \"Filling the Order would result in the creation of a Stop Loss \"\n            \"Order whose TimeInForce value is invalid. A likely cause would \"\n            \"be if the Account requires guaranteed stop loss orders and the \"\n            \"TimeInForce value were not GTC.\",\n        \"STOP_LOSS_ON_FILL_TRIGGER_CONDITION_INVALID\":\n            \"Filling the Order would result in the creation of a Stop Loss \"\n            \"Order whose TriggerCondition value is invalid. A likely cause \"\n            \"would be if the stop loss order is guaranteed and the \"\n            \"TimeInForce is not TRIGGER_DEFAULT or TRIGGER_BID for a long \"\n            \"trade, or not TRIGGER_DEFAULT or TRIGGER_ASK for a short trade.\",\n        \"TAKE_PROFIT_ON_FILL_PRICE_DISTANCE_MAXIMUM_EXCEEDED\":\n            \"Filling the Order would result in the creation of a Take Profit \"\n            \"Order whose price would be zero or negative due to the specified \"\n            \"distance.\",\n        \"TRAILING_STOP_LOSS_ON_FILL_GTD_TIMESTAMP_IN_PAST\":\n            \"Filling the Order would have resulted in the creation of a\"\n            \"Trailing Stop Loss Order with a GTD time in the past.\",\n        \"CLIENT_TRADE_ID_ALREADY_EXISTS\":\n            \"Filling the Order would result in the creation of a \"\n            \"new Open Trade with a client Trade ID already in use.\",\n        \"POSITION_CLOSEOUT_FAILED\": \"Closing out a position wasn’t \"\n                                    \"fully possible.\",\n        \"OPEN_TRADES_ALLOWED_EXCEEDED\":\n            \"Filling the Order would cause the maximum open trades \"\n            \"allowed for the Account to be exceeded.\",\n        \"PENDING_ORDERS_ALLOWED_EXCEEDED\":\n            \"Filling the Order would have resulted in exceeding the \"\n            \"number of pending Orders allowed for the Account.\",\n        \"TAKE_PROFIT_ON_FILL_CLIENT_ORDER_ID_ALREADY_EXISTS\":\n            \"Filling the Order would have resulted in the creation of \"\n            \"a Take Profit Order with a client Order ID that is already \"\n            \"in use.\",\n        \"STOP_LOSS_ON_FILL_CLIENT_ORDER_ID_ALREADY_EXISTS\":\n            \"Filling the Order would have resulted in the creation of a \"\n            \"Stop Loss Order with a client Order ID that is already in use.\",\n        \"TRAILING_STOP_LOSS_ON_FILL_CLIENT_ORDER_ID_ALREADY_EXISTS\":\n            \"Filling the Order would have resulted in the creation of a \"\n            \"Trailing Stop Loss Order with a client Order ID that is \"\n            \"already in use.\",\n        \"POSITION_SIZE_EXCEEDED\":\n            \"Filling the Order would have resulted in the \"\n            \"Account’s maximum position size limit being exceeded \"\n            \"for the Order’s instrument.\",\n        \"HEDGING_GSLO_VIOLATION\":\n            \"Filling the Order would result in the creation of a Trade, \"\n            \"however there already exists an opposing (hedged) Trade that \"\n            \"has a guaranteed Stop Loss Order attached to it. Guaranteed \"\n            \"Stop Loss Orders cannot be combined with hedged positions\",\n        \"ACCOUNT_POSITION_VALUE_LIMIT_EXCEEDED\":\n            \"Filling the order would cause the maximum position value \"\n            \"allowed for the account to be exceeded. The Order has been \"\n            \"cancelled as a result.\"\n    },\n    \"MarketOrderMarginCloseoutReason\": {\n        \"MARGIN_CHECK_VIOLATION\": \"Trade closures resulted from violating \"\n                                  \"OANDA’s margin policy\",\n        \"REGULATORY_MARGIN_CALL_VIOLATION\":\n            \"Trade closures came from a margin closeout event resulting \"\n            \"from regulatory conditions placed on the Account’s margin call\"\n    },\n    \"TransactionRejectReason\": {\n        \"INTERNAL_SERVER_ERROR\": \"An unexpected internal server error has \"\n                                 \"occurred\",\n        \"INSTRUMENT_PRICE_UNKNOWN\": \"The system was unable to determine the \"\n                                    \"current price for the Order’s instrument\",\n        \"ACCOUNT_NOT_ACTIVE\": \"The Account is not active\",\n        \"ACCOUNT_LOCKED\": \"The Account is locked\",\n        \"ACCOUNT_ORDER_CREATION_LOCKED\": \"The Account is locked for Order \"\n                                         \"creation\",\n        \"ACCOUNT_CONFIGURATION_LOCKED\": \"The Account is locked for \"\n                                        \"configuration\",\n        \"ACCOUNT_DEPOSIT_LOCKED\": \"The Account is locked for deposits\",\n        \"ACCOUNT_WITHDRAWAL_LOCKED\": \"The Account is locked for withdrawals\",\n        \"ACCOUNT_ORDER_CANCEL_LOCKED\": \"The Account is locked for Order \"\n                                       \"cancellation\",\n        \"INSTRUMENT_NOT_TRADEABLE\": \"The instrument specified is not \"\n                                    \"tradeable by the Account\",\n        \"PENDING_ORDERS_ALLOWED_EXCEEDED\": \"Creating the Order would result \"\n                                           \"in the maximum number of allowed \"\n                                           \"pending Orders being exceeded\",\n        \"ORDER_ID_UNSPECIFIED\": \"Neither the Order ID nor client Order ID \"\n                                \"are specified\",\n        \"ORDER_DOESNT_EXIST\": \"The Order specified does not exist\",\n        \"ORDER_IDENTIFIER_INCONSISTENCY\": \"The Order ID and client Order ID \"\n                                          \"specified do not identify the \"\n                                          \"same Order\",\n        \"TRADE_ID_UNSPECIFIED\": \"Neither the Trade ID nor client Trade ID \"\n                                \"are specified\",\n        \"TRADE_DOESNT_EXIST\": \"The Trade specified does not exist\",\n        \"TRADE_IDENTIFIER_INCONSISTENCY\": \"The Trade ID and client Trade ID \"\n                                          \"specified do not identify the \"\n                                          \"same Trade\",\n        \"INSUFFICIENT_MARGIN\":\n            \"The Account had insufficient margin to perform the action \"\n            \"specified. One possible reason for this is due to the creation \"\n            \"or modification of a guaranteed StopLoss Order.\",\n        \"INSTRUMENT_MISSING\": \"Order instrument has not been specified\",\n        \"INSTRUMENT_UNKNOWN\": \"The instrument specified is unknown\",\n        \"UNITS_MISSING\": \"Order units have not been not specified\",\n        \"UNITS_INVALID\": \"Order units specified are invalid\",\n        \"UNITS_PRECISION_EXCEEDED\": \"The units specified contain more \"\n                                    \"precision than is allowed for the \"\n                                    \"Order’s instrument\",\n        \"UNITS_LIMIT_EXCEEDED\": \"The units specified exceeds the maximum \"\n                                \"number of units allowed\",\n        \"UNITS_MIMIMUM_NOT_MET\": \"The units specified is less than the \"\n                                 \"minimum number of units required\",\n        \"PRICE_MISSING\": \"The price has not been specified\",\n        \"PRICE_INVALID\": \"The price specifed is invalid\",\n        \"PRICE_PRECISION_EXCEEDED\": \"The price specified contains more \"\n                                    \"precision than is allowed for the \"\n                                    \"instrument\",\n        \"PRICE_DISTANCE_MISSING\": \"The price distance has not been specified\",\n        \"PRICE_DISTANCE_INVALID\": \"The price distance specifed is invalid\",\n        \"PRICE_DISTANCE_PRECISION_EXCEEDED\": \"The price distance specified \"\n                                             \"contains more precision than is \"\n                                             \"allowed for the instrument\",\n        \"PRICE_DISTANCE_MAXIMUM_EXCEEDED\": \"The price distance exceeds that \"\n                                           \"maximum allowed amount\",\n        \"PRICE_DISTANCE_MINIMUM_NOT_MET\": \"The price distance does not meet \"\n                                          \"the minimum allowed amount\",\n        \"TIME_IN_FORCE_MISSING\": \"The TimeInForce field has not been \"\n                                 \"specified\",\n        \"TIME_IN_FORCE_INVALID\": \"The TimeInForce specified is invalid\",\n        \"TIME_IN_FORCE_GTD_TIMESTAMP_MISSING\": \"The TimeInForce is GTD but no \"\n                                               \"GTD timestamp is provided\",\n        \"TIME_IN_FORCE_GTD_TIMESTAMP_IN_PAST\": \"The TimeInForce is GTD but \"\n                                               \"the GTD timestamp is in the \"\n                                               \"past\",\n        \"PRICE_BOUND_INVALID\": \"The price bound specified is invalid\",\n        \"PRICE_BOUND_PRECISION_EXCEEDED\": \"The price bound specified contains \"\n                                          \"more precision than is allowed for \"\n                                          \"the Order’s instrument\",\n        \"ORDERS_ON_FILL_DUPLICATE_CLIENT_ORDER_IDS\":\n            \"Multiple Orders on fill share the same client Order ID\",\n        \"TRADE_ON_FILL_CLIENT_EXTENSIONS_NOT_SUPPORTED\":\n            \"The Order does not support Trade on fill client extensions \"\n            \"because it cannot create a new Trade\",\n        \"CLIENT_ORDER_ID_INVALID\": \"The client Order ID specified is invalid\",\n        \"CLIENT_ORDER_ID_ALREADY_EXISTS\":\n            \"The client Order ID specified is already assigned to another \"\n            \"pending Order\",\n        \"CLIENT_ORDER_TAG_INVALID\":\n            \"The client Order tag specified is invalid\",\n        \"CLIENT_ORDER_COMMENT_INVALID\":\n            \"The client Order comment specified is invalid\",\n        \"CLIENT_TRADE_ID_INVALID\": \"The client Trade ID specified is invalid\",\n        \"CLIENT_TRADE_ID_ALREADY_EXISTS\":\n            \"The client Trade ID specifed is already assigned to another \"\n            \"open Trade\",\n        \"CLIENT_TRADE_TAG_INVALID\":\n            \"The client Trade tag specified is invalid\",\n        \"CLIENT_TRADE_COMMENT_INVALID\": \"The client Trade comment is invalid\",\n        \"ORDER_FILL_POSITION_ACTION_MISSING\":\n            \"The OrderFillPositionAction field has not been specified\",\n        \"ORDER_FILL_POSITION_ACTION_INVALID\":\n            \"The OrderFillPositionAction specified is invalid\",\n        \"TRIGGER_CONDITION_MISSING\":\n            \"The TriggerCondition field has not been specified\",\n        \"TRIGGER_CONDITION_INVALID\":\n            \"The TriggerCondition specified is invalid\",\n        \"ORDER_PARTIAL_FILL_OPTION_MISSING\":\n            \"The OrderFillPositionAction field has not been specified\",\n        \"ORDER_PARTIAL_FILL_OPTION_INVALID\":\n            \"The OrderFillPositionAction specified is invalid.\",\n        \"INVALID_REISSUE_IMMEDIATE_PARTIAL_FILL\":\n            \"When attempting to reissue an order (currently only a \"\n            \"MarketIfTouched) that was immediately partially filled, it is \"\n            \"not possible to create a correct pending Order.\",\n        \"TAKE_PROFIT_ORDER_ALREADY_EXISTS\":\n            \"A Take Profit Order for the specified Trade already exists\",\n        \"TAKE_PROFIT_ON_FILL_PRICE_MISSING\":\n            \"The Take Profit on fill specified does not provide a price\",\n        \"TAKE_PROFIT_ON_FILL_PRICE_INVALID\":\n            \"The Take Profit on fill specified contains an invalid price\",\n        \"TAKE_PROFIT_ON_FILL_PRICE_PRECISION_EXCEEDED\":\n            \"The Take Profit on fill specified contains a price with more \"\n            \"precision than is allowed by the Order’s instrument\",\n        \"TAKE_PROFIT_ON_FILL_TIME_IN_FORCE_MISSING\":\n            \"The Take Profit on fill specified does not provide a TimeInForce\",\n        \"TAKE_PROFIT_ON_FILL_TIME_IN_FORCE_INVALID\":\n            \"The Take Profit on fill specifies an invalid TimeInForce\",\n        \"TAKE_PROFIT_ON_FILL_GTD_TIMESTAMP_MISSING\":\n            \"The Take Profit on fill specifies a GTD TimeInForce but does \"\n            \"not provide a GTD timestamp\",\n        \"TAKE_PROFIT_ON_FILL_GTD_TIMESTAMP_IN_PAST\":\n            \"The Take Profit on fill specifies a GTD timestamp that is in \"\n            \"the past\",\n        \"TAKE_PROFIT_ON_FILL_CLIENT_ORDER_ID_INVALID\":\n            \"The Take Profit on fill client Order ID specified is invalid\",\n        \"TAKE_PROFIT_ON_FILL_CLIENT_ORDER_TAG_INVALID\":\n            \"The Take Profit on fill client Order tag specified is invalid\",\n        \"TAKE_PROFIT_ON_FILL_CLIENT_ORDER_COMMENT_INVALID\":\n            \"The Take Profit on fill client Order comment specified is \"\n            \"invalid\",\n        \"TAKE_PROFIT_ON_FILL_TRIGGER_CONDITION_MISSING\":\n            \"The Take Profit on fill specified does not provide a \"\n            \"TriggerCondition\",\n        \"TAKE_PROFIT_ON_FILL_TRIGGER_CONDITION_INVALID\":\n            \"The Take Profit on fill specifies an invalid TriggerCondition\",\n        \"STOP_LOSS_ORDER_ALREADY_EXISTS\":\n            \"A Stop Loss Order for the specified Trade already exists\",\n        \"STOP_LOSS_ORDER_GUARANTEED_REQUIRED\":\n            \"An attempt was made to to create a non-guaranteed stop loss \"\n            \"order in an account that requires all stop loss orders to be \"\n            \"guaranteed.\",\n        \"STOP_LOSS_ORDER_GUARANTEED_PRICE_WITHIN_SPREAD\":\n            \"An attempt to create a guaranteed stop loss order with a price \"\n            \"that is within the current tradeable spread.\",\n        \"STOP_LOSS_ORDER_GUARANTEED_NOT_ALLOWED\":\n            \"An attempt was made to create a guaranteed Stop Loss Order, \"\n            \"however the Account’s configuration does not allow guaranteed \"\n            \"Stop Loss Orders.\",\n        \"STOP_LOSS_ORDER_GUARANTEED_HALTED_CREATE_VIOLATION\":\n            \"An attempt was made to create a guaranteed Stop Loss Order \"\n            \"when the market was halted.\",\n        \"STOP_LOSS_ORDER_GUARANTEED_HALTED_TIGHTEN_VIOLATION\":\n            \"An attempt was made to re-create a guaranteed Stop Loss Order\"\n            \"with a tighter fill price when the market was halted.\",\n        \"STOP_LOSS_ORDER_GUARANTEED_HEDGING_NOT_ALLOWED\":\n            \"An attempt was made to create a guaranteed Stop Loss Order on \"\n            \"a hedged Trade (ie there is an existing open Trade in the \"\n            \"opposing direction), however the Account’s configuration does \"\n            \"not allow guaranteed Stop Loss Orders for hedged \"\n            \"Trades/Positions.\",\n        \"STOP_LOSS_ORDER_GUARANTEED_MINIMUM_DISTANCE_NOT_MET\":\n            \"An attempt was made to create a guaranteed Stop Loss Order, \"\n            \"however the distance between the current price and the trigger \"\n            \"price does not meet the Account’s configured \"\n            \"minimumGuaranteedStopLossDistance.\",\n        \"STOP_LOSS_ORDER_NOT_CANCELABLE\":\n            \"An attempt was made to cancel a Stop Loss Order, however the \"\n            \"Account’s configuration requires every Trade have an associated \"\n            \"Stop Loss Order.\",\n        \"STOP_LOSS_ORDER_NOT_REPLACEABLE\":\n            \"An attempt was made to cancel and replace a Stop Loss Order, \"\n            \"however the Account’s configuration prevents the modification \"\n            \"of Stop Loss Orders.\",\n        \"STOP_LOSS_ORDER_GUARANTEED_LEVEL_RESTRICTION_EXCEEDED\":\n            \"An attempt was made to create a guaranteed Stop Loss Order, \"\n            \"however doing so would exceed the Account’s configured \"\n            \"guaranteed StopLoss Order level restriction volume.\",\n        \"STOP_LOSS_ORDER_PRICE_AND_DISTANCE_BOTH_SPECIFIED\":\n            \"The Stop Loss Order request contains both the price and \"\n            \"distance fields.\",\n        \"STOP_LOSS_ORDER_PRICE_AND_DISTANCE_BOTH_MISSING\":\n            \"The Stop Loss Order request contains neither the price nor \"\n            \"distance fields.\",\n        \"STOP_LOSS_ON_FILL_REQUIRED_FOR_PENDING_ORDER\":\n            \"An attempt to create a pending Order was made with no Stop \"\n            \"Loss Order on fill specified and the Account’s configuration \"\n            \"requires that every Trade have an associated Stop Loss Order.\",\n        \"STOP_LOSS_ON_FILL_GUARANTEED_NOT_ALLOWED\":\n            \"An attempt to create a pending Order was made with a Stop \"\n            \"Loss Order on fill that was explicitly configured to be \"\n            \"guaranteed, however the Account’s configuration does not allow \"\n            \"guaranteed Stop Loss Orders.\",\n        \"STOP_LOSS_ON_FILL_GUARANTEED_REQUIRED\":\n            \"An attempt to create a pending Order was made with a Stop Loss \"\n            \"Order on fill that was explicitly configured to be not \"\n            \"guaranteed, however the Account’s configuration requires \"\n            \"guaranteed Stop Loss Orders.\",\n        \"STOP_LOSS_ON_FILL_PRICE_MISSING\":\n            \"The Stop Loss on fill specified does not provide a price\",\n        \"STOP_LOSS_ON_FILL_PRICE_INVALID\":\n            \"The Stop Loss on fill specifies an invalid price\",\n        \"STOP_LOSS_ON_FILL_PRICE_PRECISION_EXCEEDED\":\n            \"The Stop Loss on fill specifies a price with more precision \"\n            \"than is allowed by the Order’s instrument\",\n        \"STOP_LOSS_ON_FILL_GUARANTEED_MINIMUM_DISTANCE_NOT_MET\":\n            \"An attempt to create a pending Order was made with the \"\n            \"distance between the guaranteed Stop Loss Order on fill’s price \"\n            \"and the pending Order’s price is less than the Account’s \"\n            \"configured minimum guaranteed stop loss distance.\",\n        \"STOP_LOSS_ON_FILL_GUARANTEED_LEVEL_RESTRICTION_EXCEEDED\":\n            \"An attempt to create a pending Order was made with a guaranteed \"\n            \"Stop Loss Order on fill configured, and the Order’s units \"\n            \"exceed the Account’s configured guaranteed StopLoss Order level \"\n            \"restriction volume.\",\n        \"STOP_LOSS_ON_FILL_DISTANCE_INVALID\":\n            \"The Stop Loss on fill distance is invalid\",\n        \"STOP_LOSS_ON_FILL_PRICE_DISTANCE_MAXIMUM_EXCEEDED\":\n            \"The Stop Loss on fill price distance exceeds the maximum \"\n            \"allowed amount\",\n        \"STOP_LOSS_ON_FILL_DISTANCE_PRECISION_EXCEEDED\":\n            \"The Stop Loss on fill distance contains more precision than \"\n            \"is allowed by the instrument\",\n        \"STOP_LOSS_ON_FILL_PRICE_AND_DISTANCE_BOTH_SPECIFIED\":\n            \"The Stop Loss on fill contains both the price and distance \"\n            \"fields.\",\n        \"STOP_LOSS_ON_FILL_PRICE_AND_DISTANCE_BOTH_MISSING\":\n            \"The Stop Loss on fill contains neither the price nor distance \"\n            \"fields.\",\n        \"STOP_LOSS_ON_FILL_TIME_IN_FORCE_MISSING\":\n            \"The Stop Loss on fill specified does not provide a TimeInForce\",\n        \"STOP_LOSS_ON_FILL_TIME_IN_FORCE_INVALID\":\n            \"The Stop Loss on fill specifies an invalid TimeInForce\",\n        \"STOP_LOSS_ON_FILL_GTD_TIMESTAMP_MISSING\":\n            \"The Stop Loss on fill specifies a GTD TimeInForce but does \"\n            \"not provide a GTD timestamp\",\n        \"STOP_LOSS_ON_FILL_GTD_TIMESTAMP_IN_PAST\":\n            \"The Stop Loss on fill specifies a GTD timestamp that is in \"\n            \"the past\",\n        \"STOP_LOSS_ON_FILL_CLIENT_ORDER_ID_INVALID\":\n            \"The Stop Loss on fill client Order ID specified is invalid\",\n        \"STOP_LOSS_ON_FILL_CLIENT_ORDER_TAG_INVALID\":\n            \"The Stop Loss on fill client Order tag specified is invalid\",\n        \"STOP_LOSS_ON_FILL_CLIENT_ORDER_COMMENT_INVALID\":\n            \"The Stop Loss on fill client Order comment specified is invalid\",\n        \"STOP_LOSS_ON_FILL_TRIGGER_CONDITION_MISSING\":\n            \"The Stop Loss on fill specified does not provide a \"\n            \"TriggerCondition\",\n        \"STOP_LOSS_ON_FILL_TRIGGER_CONDITION_INVALID\":\n            \"The Stop Loss on fill specifies an invalid TriggerCondition\",\n        \"TRAILING_STOP_LOSS_ORDER_ALREADY_EXISTS\":\n            \"A Trailing Stop Loss Order for the specified Trade already \"\n            \"exists\",\n        \"TRAILING_STOP_LOSS_ON_FILL_PRICE_DISTANCE_MISSING\":\n            \"The Trailing Stop Loss on fill specified does not provide a \"\n            \"distance\",\n        \"TRAILING_STOP_LOSS_ON_FILL_PRICE_DISTANCE_INVALID\":\n            \"The Trailing Stop Loss on fill distance is invalid\",\n        \"TRAILING_STOP_LOSS_ON_FILL_PRICE_DISTANCE_PRECISION_EXCEEDED\":\n            \"The Trailing Stop Loss on fill distance contains more precision \"\n            \"than is allowed by the instrument\",\n        \"TRAILING_STOP_LOSS_ON_FILL_PRICE_DISTANCE_MAXIMUM_EXCEEDED\":\n            \"The Trailing Stop Loss on fill price distance exceeds the \"\n            \"maximum allowed amount\",\n        \"TRAILING_STOP_LOSS_ON_FILL_PRICE_DISTANCE_MINIMUM_NOT_MET\":\n            \"The Trailing Stop Loss on fill price distance does not meet \"\n            \"the minimum allowed amount\",\n        \"TRAILING_STOP_LOSS_ON_FILL_TIME_IN_FORCE_MISSING\":\n            \"The Trailing Stop Loss on fill specified does not provide a \"\n            \"TimeInForce\",\n        \"TRAILING_STOP_LOSS_ON_FILL_TIME_IN_FORCE_INVALID\":\n            \"The Trailing Stop Loss on fill specifies an invalid TimeInForce\",\n        \"TRAILING_STOP_LOSS_ON_FILL_GTD_TIMESTAMP_MISSING\":\n            \"The Trailing Stop Loss on fill TimeInForce is specified as GTD \"\n            \"but no GTD timestamp is provided\",\n        \"TRAILING_STOP_LOSS_ON_FILL_GTD_TIMESTAMP_IN_PAST\":\n            \"The Trailing Stop Loss on fill GTD timestamp is in the past\",\n        \"TRAILING_STOP_LOSS_ON_FILL_CLIENT_ORDER_ID_INVALID\":\n            \"The Trailing Stop Loss on fill client Order ID specified is \"\n            \"invalid\",\n        \"TRAILING_STOP_LOSS_ON_FILL_CLIENT_ORDER_TAG_INVALID\":\n            \"The Trailing Stop Loss on fill client Order tag specified is \"\n            \"invalid\",\n        \"TRAILING_STOP_LOSS_ON_FILL_CLIENT_ORDER_COMMENT_INVALID\":\n            \"The Trailing Stop Loss on fill client Order comment specified \"\n            \"is invalid\",\n        \"TRAILING_STOP_LOSS_ORDERS_NOT_SUPPORTED\":\n            \"A client attempted to create either a Trailing Stop Loss order \"\n            \"or an order with a Trailing Stop Loss On Fill specified, which \"\n            \"may not yet be supported.\",\n        \"TRAILING_STOP_LOSS_ON_FILL_TRIGGER_CONDITION_MISSING\":\n            \"The Trailing Stop Loss on fill specified does not provide a \"\n            \"TriggerCondition\",\n        \"TRAILING_STOP_LOSS_ON_FILL_TRIGGER_CONDITION_INVALID\":\n            \"The Tailing Stop Loss on fill specifies an invalid \"\n            \"TriggerCondition\",\n        \"CLOSE_TRADE_TYPE_MISSING\": \"The request to close a Trade does not \"\n                                    \"specify a full or partial close\",\n        \"CLOSE_TRADE_PARTIAL_UNITS_MISSING\":\n            \"The request to close a Trade partially did not specify the \"\n            \"number of units to close\",\n        \"CLOSE_TRADE_UNITS_EXCEED_TRADE_SIZE\":\n            \"The request to partially close a Trade specifies a number of \"\n            \"units that exceeds the current size of the given Trade\",\n        \"CLOSEOUT_POSITION_DOESNT_EXIST\":\n            \"The Position requested to be closed out does not exist\",\n        \"CLOSEOUT_POSITION_INCOMPLETE_SPECIFICATION\":\n            \"The request to closeout a Position was specified incompletely\",\n        \"CLOSEOUT_POSITION_UNITS_EXCEED_POSITION_SIZE\":\n            \"A partial Position closeout request specifies a number of units \"\n            \"that exceeds the current Position\",\n        \"CLOSEOUT_POSITION_REJECT\":\n            \"The request to closeout a Position could not be fully satisfied\",\n        \"CLOSEOUT_POSITION_PARTIAL_UNITS_MISSING\":\n            \"The request to partially closeout a Position did not specify \"\n            \"the number of units to close.\",\n        \"MARKUP_GROUP_ID_INVALID\": \"The markup group ID provided is invalid\",\n        \"POSITION_AGGREGATION_MODE_INVALID\":\n            \"The PositionAggregationMode provided is not supported/valid.\",\n        \"ADMIN_CONFIGURE_DATA_MISSING\": \"No configuration parameters provided\",\n        \"MARGIN_RATE_INVALID\": \"The margin rate provided is invalid\",\n        \"MARGIN_RATE_WOULD_TRIGGER_CLOSEOUT\": \"The margin rate provided \"\n                                              \"would cause an immediate \"\n                                              \"margin closeout\",\n        \"ALIAS_INVALID\": \"The account alias string provided is invalid\",\n        \"CLIENT_CONFIGURE_DATA_MISSING\":\n            \"No configuration parameters provided\",\n        \"MARGIN_RATE_WOULD_TRIGGER_MARGIN_CALL\":\n            \"The margin rate provided would cause the Account to enter \"\n            \"a margin call state.\",\n        \"AMOUNT_INVALID\": \"Funding is not possible because the requested \"\n                          \"transfer amount is invalid\",\n        \"INSUFFICIENT_FUNDS\": \"The Account does not have sufficient \"\n                              \"balance to complete the funding request\",\n        \"AMOUNT_MISSING\": \"Funding amount has not been specified\",\n        \"FUNDING_REASON_MISSING\": \"Funding reason has not been specified\",\n        \"CLIENT_EXTENSIONS_DATA_MISSING\":\n            \"Neither Order nor Trade on Fill client extensions were \"\n            \"provided for modification\",\n        \"REPLACING_ORDER_INVALID\":\n            \"The Order to be replaced has a different type than the \"\n            \"replacing Order.\",\n        \"REPLACING_TRADE_ID_INVALID\":\n            \"The replacing Order refers to a different Trade than the \"\n            \"Order that is being replaced.\",\n     }\n}\n"
  },
  {
    "path": "oandapyV20/endpoints/__init__.py",
    "content": ""
  },
  {
    "path": "oandapyV20/endpoints/accounts.py",
    "content": "# -*- coding: utf-8 -*-\n\"\"\"Handle account endpoints.\"\"\"\nfrom .apirequest import APIRequest\nfrom .decorators import dyndoc_insert, endpoint\nfrom .responses.accounts import responses\nfrom abc import abstractmethod\n\n\nclass Accounts(APIRequest):\n    \"\"\"Accounts - class to handle the accounts endpoints.\"\"\"\n\n    ENDPOINT = \"\"\n    METHOD = \"GET\"\n\n    @abstractmethod\n    @dyndoc_insert(responses)\n    def __init__(self, accountID=None):\n        \"\"\"Instantiate an Accounts APIRequest instance.\n\n        Parameters\n        ----------\n        accountID : string (optional)\n            the accountID of the account. Optional when requesting\n            all accounts. For all other requests to the endpoint it is\n            required.\n\n        \"\"\"\n        endpoint = self.ENDPOINT.format(accountID=accountID)\n        super(Accounts, self).__init__(endpoint, method=self.METHOD)\n\n\n@endpoint(\"v3/accounts\")\nclass AccountList(Accounts):\n    \"\"\"Get a list of all Accounts authorized for the provided token.\"\"\"\n\n    @dyndoc_insert(responses)\n    def __init__(self):\n        \"\"\"Instantiate an AccountList request.\n\n        >>> import oandapyV20\n        >>> import oandapyV20.endpoints.accounts as accounts\n        >>> client = oandapyV20.API(access_token=...)\n        >>> r = accounts.AccountList()\n        >>> client.request(r)\n        >>> print r.response\n\n        ::\n\n            {_v3_accounts_resp}\n\n        \"\"\"\n        super(AccountList, self).__init__()\n\n\n@endpoint(\"v3/accounts/{accountID}\")\nclass AccountDetails(Accounts):\n    \"\"\"AccountDetails.\n\n    Get the full details for a single Account that a client has access\n    to. Full pending Order, open Trade and open Position representations are\n    provided.\n    \"\"\"\n\n    @dyndoc_insert(responses)\n    def __init__(self, accountID):\n        \"\"\"Instantiate an AccountDetails request.\n\n        Parameters\n        ----------\n        accountID : string (required)\n            id of the account to perform the request on.\n\n\n        >>> import oandapyV20\n        >>> import oandapyV20.endpoints.accounts as accounts\n        >>> client = oandapyV20.API(access_token=...)\n        >>> r = accounts.AccountDetails(accountID)\n        >>> client.request(r)\n        >>> print r.response\n\n        ::\n\n            {_v3_account_by_accountID_resp}\n\n        \"\"\"\n        super(AccountDetails, self).__init__(accountID)\n\n\n@endpoint(\"v3/accounts/{accountID}/summary\")\nclass AccountSummary(Accounts):\n    \"\"\"Get a summary for a single Account that a client has access to.\"\"\"\n\n    @dyndoc_insert(responses)\n    def __init__(self, accountID):\n        \"\"\"Instantiate an AccountSummary request.\n\n        Parameters\n        ----------\n        accountID : string (required)\n            id of the account to perform the request on.\n\n\n        >>> import oandapyV20\n        >>> import oandapyV20.endpoints.accounts as accounts\n        >>> client = oandapyV20.API(access_token=...)\n        >>> r = accounts.AccountSummary(accountID)\n        >>> client.request(r)\n        >>> print r.response\n\n        ::\n\n            {_v3_account_by_accountID_summary_resp}\n\n        \"\"\"\n        super(AccountSummary, self).__init__(accountID)\n\n\n@endpoint(\"v3/accounts/{accountID}/instruments\")\nclass AccountInstruments(Accounts):\n    \"\"\"AccountInstruments.\n\n    Get the list of tradable instruments for the given Account. The list of\n    tradeable instruments is dependent on the regulatory division that the\n    Account is located in, thus should be the same for all Accounts owned by a\n    single user.\n    \"\"\"\n\n    @dyndoc_insert(responses)\n    def __init__(self, accountID, params=None):\n        \"\"\"Instantiate an AccountInstruments request.\n\n        Parameters\n        ----------\n        accountID : string (required)\n            id of the account to perform the request on.\n\n        params : dict (optional)\n            query params to send, check developer.oanda.com for details.\n\n\n        Query Params example::\n\n            {_v3_account_by_accountID_instruments_params}\n\n\n        >>> import oandapyV20\n        >>> import oandapyV20.endpoints.accounts as accounts\n        >>> client = oandapyV20.API(access_token=...)\n        >>> params = ...\n        >>> r = accounts.AccountInstruments(accountID=..., params=params)\n        >>> client.request(r)\n        >>> print r.response\n\n        Output::\n\n            {_v3_account_by_accountID_instruments_resp}\n\n        \"\"\"\n        super(AccountInstruments, self).__init__(accountID)\n        self.params = params\n\n\n@endpoint(\"v3/accounts/{accountID}/configuration\", \"PATCH\")\nclass AccountConfiguration(Accounts):\n    \"\"\"Set the client-configurable portions of an Account.\"\"\"\n\n    HEADERS = {\"Content-Type\": \"application/json\"}\n\n    @dyndoc_insert(responses)\n    def __init__(self, accountID, data):\n        \"\"\"Instantiate an AccountConfiguration request.\n\n        Parameters\n        ----------\n        accountID : string (required)\n            id of the account to perform the request on.\n\n        data : dict (required)\n            json body to send\n\n\n        body example::\n\n            {_v3_accounts_accountID_account_config_body}\n\n        >>> import oandapyV20\n        >>> import oandapyV20.endpoints.accounts as accounts\n        >>> client = oandapyV20.API(access_token=...)\n        >>> r = accounts.AccountConfiguration(accountID, data=data)\n        >>> client.request(r)\n        >>> print r.response\n\n        ::\n\n            {_v3_accounts_accountID_account_config_resp}\n\n        \"\"\"\n        super(AccountConfiguration, self).__init__(accountID)\n        self.data = data\n\n\n@endpoint(\"v3/accounts/{accountID}/changes\")\nclass AccountChanges(Accounts):\n    \"\"\"AccountChanges.\n\n    Endpoint used to poll an Account for its current state and changes\n    since a specified TransactionID.\n    \"\"\"\n\n    @dyndoc_insert(responses)\n    def __init__(self, accountID, params=None):\n        \"\"\"Instantiate an AccountChanges request.\n\n        Parameters\n        ----------\n        accountID : string (required)\n            id of the account to perform the request on.\n\n        params : dict (optional)\n            query params to send, check developer.oanda.com for details.\n\n\n        Query Params example::\n\n            {_v3_accounts_accountID_account_changes_params}\n\n        >>> import oandapyV20\n        >>> import oandapyV20.endpoints.accounts as accounts\n        >>> client = oandapyV20.API(access_token=...)\n        >>> params = ...\n        >>> r = accounts.AccountChanges(accountID=..., params=params)\n        >>> client.request(r)\n        >>> print r.response\n\n        Output::\n\n            {_v3_accounts_accountID_account_changes_resp}\n\n        \"\"\"\n        super(AccountChanges, self).__init__(accountID)\n        self.params = params\n"
  },
  {
    "path": "oandapyV20/endpoints/apirequest.py",
    "content": "\"\"\"Handling of API requests.\"\"\"\nimport six\nfrom abc import ABCMeta, abstractmethod\n\n\n@six.add_metaclass(ABCMeta)\nclass APIRequest(object):\n    \"\"\"Base Class for API-request classes.\"\"\"\n\n    @abstractmethod\n    def __init__(self, endpoint, method=\"GET\", expected_status=200):\n        \"\"\"Instantiate an API request.\n\n        Parameters\n        ----------\n        endpoint : string\n            the URL format string\n\n        method : string\n            the method for the request. Default: GET.\n        \"\"\"\n        self._expected_status = expected_status\n        self._status_code = None\n        self._response = None\n\n        self._endpoint = endpoint\n        self.method = method\n\n    @property\n    def expected_status(self):\n        return self._expected_status\n\n    @property\n    def status_code(self):\n        return self._status_code\n\n    @status_code.setter\n    def status_code(self, value):\n        if value != self._expected_status:\n            raise ValueError(\"{} {} {:d}\".format(self, self.method, value))\n        self._status_code = value\n\n    @property\n    def response(self):\n        \"\"\"response - get the response of the request.\"\"\"\n        return self._response\n\n    @response.setter\n    def response(self, value):\n        \"\"\"response - set the response of the request.\"\"\"\n        self._response = value\n\n    def __str__(self):\n        \"\"\"return the endpoint.\"\"\"\n        return self._endpoint\n"
  },
  {
    "path": "oandapyV20/endpoints/decorators.py",
    "content": "# -*- coding: UTF-8 -*-\n\"\"\"decorators.\"\"\"\n\n\ndef dyndoc_insert(src):\n    \"\"\"docstring_insert - a decorator to insert API-docparts dynamically.\"\"\"\n    # manipulating docstrings this way is tricky due to indentation\n    # the JSON needs leading whitespace to be interpreted correctly\n    import json\n    import re\n\n    def mkblock(d, flag=0):\n        # response, pretty formatted\n        v = json.dumps(d, indent=2)\n        if flag == 1:\n            # strip the '[' and ']' in case of a list holding items\n            # that stand on their own (example: tick records from a stream)\n            nw = re.findall('.*?\\[(.*)\\]', v, flags=re.S)\n            v = nw[0]\n        # add leading whitespace for each line and start with a newline\n        return \"\\n{}\".format(\"\".join([\"{0:>16}{1}\\n\".format(\"\", L)\n                             for L in v.split('\\n')]))\n\n    def dec(obj):\n        allSlots = re.findall(\"\\{(_v3.*?)\\}\", obj.__doc__)\n        docsub = {}\n        sub = {}\n        for k in allSlots:\n            p = re.findall(\"^(_v3.*)_(.*)\", k)\n            p = list(*p)\n            sub.update({p[1]: p[0]})\n\n        for v in sub.values():\n            for k in sub.keys():\n                docsub[\"{}_url\".format(v)] = \"{}\".format(src[v][\"url\"])\n                if \"resp\" == k:\n                    docsub.update({\"{}_resp\".format(v):\n                                   mkblock(src[v][\"response\"])})\n                if \"body\" == k:\n                    docsub.update({\"{}_body\".format(v):\n                                   mkblock(src[v][\"body\"])})\n\n                if \"params\" == k:\n                    docsub.update({\"{}_params\".format(v):\n                                   mkblock(src[v][\"params\"])})\n                if \"ciresp\" == k:\n                    docsub.update({\"{}_ciresp\".format(v):\n                                   mkblock(src[v][\"response\"], 1)})\n\n        obj.__doc__ = obj.__doc__.format(**docsub)\n\n        return obj\n\n    return dec\n\n\ndef endpoint(url, method=\"GET\", expected_status=200):\n    \"\"\"endpoint - decorator to manipulate the REST-service endpoint.\n\n    The endpoint decorator sets the endpoint and the method for the class\n    to access the REST-service.\n    \"\"\"\n    def dec(obj):\n        obj.ENDPOINT = url\n        obj.METHOD = method\n        obj.EXPECTED_STATUS = expected_status\n        return obj\n\n    return dec\n\n\ndef abstractclass(cls):\n    \"\"\"abstractclass - class decorator.\n\n    make sure the class is abstract and cannot be used on it's own.\n\n    @abstractclass\n    class A(object):\n        def __init__(self, *args, **kwargs):\n            # logic\n            pass\n\n    class B(A):\n        pass\n\n    a = A()   # results in an AssertionError\n    b = B()   # works fine\n    \"\"\"\n    setattr(cls, \"_ISNEVER\", cls.__bases__[0].__name__)\n    origInit = cls.__dict__[\"__init__\"]\n\n    def wrapInit(self, *args, **kwargs):\n        # when the class is instantiated we can check for bases\n        # we don't want it to be the base class\n        try:\n            assert self.__class__.__bases__[-1].__name__ != self._ISNEVER\n            origInit(self, *args, **kwargs)\n        except AssertionError:\n            raise TypeError(\"Use of abstract base class\")\n\n    # replace the original __init__\n    setattr(wrapInit, \"__doc__\", getattr(origInit, \"__doc__\"))\n    setattr(origInit, \"__doc__\", \"\")\n    setattr(cls, \"__init__\", wrapInit)\n\n    return cls\n\n\nclass extendargs(object):\n    \"\"\"'extendargs' decorator.\n\n    Add extra arguments to the argumentlist of the constructor of the class.\n    \"\"\"\n\n    def __init__(self, *loa):\n        self.loa = loa\n\n    def __call__(self, cls):\n        # save parent class __init__\n        origInit = cls.__bases__[0].__dict__[\"__init__\"]\n\n        def wrapInit(wself, *args, **kwargs):\n            for extraArg in self.loa:\n                if extraArg in kwargs:\n                    setattr(wself, extraArg, kwargs[extraArg])\n                    del kwargs[extraArg]\n            origInit(wself, *args, **kwargs)\n        setattr(cls, \"__init__\", wrapInit)\n\n        return cls\n"
  },
  {
    "path": "oandapyV20/endpoints/forexlabs.py",
    "content": "\"\"\"Handle forexlabs endpoints.\"\"\"\nfrom .apirequest import APIRequest\nfrom .decorators import dyndoc_insert, endpoint\nfrom .responses.forexlabs import responses\nfrom abc import abstractmethod\n\n\nclass ForexLabs(APIRequest):\n    \"\"\"ForexLabs - abstractbase class to handle the 'forexlabs' endpoints.\"\"\"\n\n    ENDPOINT = \"\"\n    METHOD = \"GET\"\n\n    @abstractmethod\n    @dyndoc_insert(responses)\n    def __init__(self):\n        \"\"\"Instantiate a ForexLabs APIRequest instance.\"\"\"\n        endpoint = self.ENDPOINT.format()\n        super(ForexLabs, self).__init__(endpoint,\n                                        method=self.METHOD)\n\n\n@endpoint(\"labs/v1/calendar\")\nclass Calendar(ForexLabs):\n    \"\"\"Calendar.\n\n    Get calendar information.\n    \"\"\"\n\n    @dyndoc_insert(responses)\n    def __init__(self, params):\n        \"\"\"Instantiate a Calendar request.\n\n        Parameters\n        ----------\n        params : dict (required)\n            query params to send, check developer.oanda.com for details.\n\n\n        >>> import oandapyV20\n        >>> import oandapyV20.endpoints.forexlabs as labs\n        >>> accountID = ...\n        >>> client = oandapyV20.API(access_token=...)\n        >>> params = {_v3_forexlabs_calendar_params}\n        >>> r = labs.Calendar(params=params)\n        >>> client.request(r)\n        >>> print(r.response)\n\n        Output::\n\n            {_v3_forexlabs_calendar_resp}\n\n        \"\"\"\n        super(Calendar, self).__init__()\n        self.params = params\n\n\n@endpoint(\"labs/v1/historical_position_ratios\")\nclass HistoricalPositionRatios(ForexLabs):\n    \"\"\"HistoricalPositionRatios.\n\n    Get the historical positionratios for an instrument.\n    \"\"\"\n\n    @dyndoc_insert(responses)\n    def __init__(self, params):\n        \"\"\"Instantiate a HistoricalPositionRatios request.\n\n        Parameters\n        ----------\n        params : dict (required)\n            query params to send, check developer.oanda.com for details.\n\n\n        >>> import oandapyV20\n        >>> import oandapyV20.endpoints.forexlabs as labs\n        >>> accountID = ...\n        >>> client = oandapyV20.API(access_token=...)\n        >>> params = {_v3_forexlabs_histposratios_params}\n        >>> r = labs.HistoricalPositionRatios(params=params)\n        >>> client.request(r)\n        >>> print(r.response)\n\n        Output::\n\n            {_v3_forexlabs_histposratios_resp}\n\n        \"\"\"\n        super(HistoricalPositionRatios, self).__init__()\n        self.params = params\n\n\n@endpoint(\"labs/v1/spreads\")\nclass Spreads(ForexLabs):\n    \"\"\"Spreads.\n\n    Get the spread information for an instrument.\n    \"\"\"\n\n    @dyndoc_insert(responses)\n    def __init__(self, params):\n        \"\"\"Instantiate a Spreads request.\n\n        Parameters\n        ----------\n        params : dict (required)\n            query params to send, check developer.oanda.com for details.\n\n\n        >>> import oandapyV20\n        >>> import oandapyV20.endpoints.forexlabs as labs\n        >>> accountID = ...\n        >>> client = oandapyV20.API(access_token=...)\n        >>> params = {_v3_forexlabs_spreads_params}\n        >>> r = labs.Spreads(params=params)\n        >>> client.request(r)\n        >>> print(r.response)\n\n        Output::\n\n            {_v3_forexlabs_spreads_resp}\n\n        \"\"\"\n        super(Spreads, self).__init__()\n        self.params = params\n\n\n@endpoint(\"labs/v1/commitments_of_traders\")\nclass CommitmentsOfTraders(ForexLabs):\n    \"\"\"CommitmentsOfTraders.\n\n    Get the 'commitments of traders' information for an instrument.\n    \"\"\"\n\n    @dyndoc_insert(responses)\n    def __init__(self, params):\n        \"\"\"Instantiate a CommitmentsOfTraders request.\n\n        Parameters\n        ----------\n        params : dict (required)\n            query params to send, check developer.oanda.com for details.\n\n\n        >>> import oandapyV20\n        >>> import oandapyV20.endpoints.forexlabs as labs\n        >>> accountID = ...\n        >>> client = oandapyV20.API(access_token=...)\n        >>> params = {_v3_forexlabs_commoftrad_params}\n        >>> r = labs.CommitmentOfTraders(params=params)\n        >>> client.request(r)\n        >>> print(r.response)\n\n        Output::\n\n            {_v3_forexlabs_commoftrad_resp}\n\n        \"\"\"\n        super(CommitmentsOfTraders, self).__init__()\n        self.params = params\n\n\n@endpoint(\"labs/v1/orderbook_data\")\nclass OrderbookData(ForexLabs):\n    \"\"\"OrderbookData.\n\n    Get the 'orderbook data' for an instrument.\n    \"\"\"\n\n    @dyndoc_insert(responses)\n    def __init__(self, params):\n        \"\"\"Instantiate an OrderbookData request.\n\n        Parameters\n        ----------\n        params : dict (required)\n            query params to send, check developer.oanda.com for details.\n\n\n        >>> import oandapyV20\n        >>> import oandapyV20.endpoints.forexlabs as labs\n        >>> accountID = ...\n        >>> client = oandapyV20.API(access_token=...)\n        >>> params = {_v3_forexlabs_orderbookdata_params}\n        >>> r = labs.CommitmentOfTraders(params=params)\n        >>> client.request(r)\n        >>> print(r.response)\n\n        Output::\n\n            {_v3_forexlabs_orderbookdata_resp}\n\n        \"\"\"\n        super(OrderbookData, self).__init__()\n        self.params = params\n\n\n@endpoint(\"labs/v1/signal/autochartist\")\nclass Autochartist(ForexLabs):\n    \"\"\"Autochartist.\n\n    Get the 'autochartist data'.\n    \"\"\"\n\n    @dyndoc_insert(responses)\n    def __init__(self, params=None):\n        \"\"\"Instantiate an Autochartist request.\n\n        Parameters\n        ----------\n        params : dict (optional)\n            query params to send, check developer.oanda.com for details.\n\n\n        >>> import oandapyV20\n        >>> import oandapyV20.endpoints.forexlabs as labs\n        >>> accountID = ...\n        >>> client = oandapyV20.API(access_token=...)\n        >>> params = {_v3_forexlabs_autochartist_params}\n        >>> r = labs.Autochartist(params=params)\n        >>> client.request(r)\n        >>> print(r.response)\n\n        Output::\n\n            {_v3_forexlabs_autochartist_resp}\n\n        \"\"\"\n        super(Autochartist, self).__init__()\n        self.params = params\n"
  },
  {
    "path": "oandapyV20/endpoints/instruments.py",
    "content": "# -*- coding: utf-8 -*-\n\"\"\"Handle instruments endpoints.\"\"\"\nfrom .apirequest import APIRequest\nfrom .decorators import dyndoc_insert, endpoint\nfrom .responses.instruments import responses\nfrom abc import abstractmethod\n\n\nclass Instruments(APIRequest):\n    \"\"\"Instruments - abstract class to handle instruments endpoint.\"\"\"\n\n    ENDPOINT = \"\"\n    METHOD = \"GET\"\n\n    @abstractmethod\n    @dyndoc_insert(responses)\n    def __init__(self, instrument):\n        \"\"\"Instantiate a Instrument APIRequest instance.\n\n        Parameters\n        ----------\n        instrument : string (required)\n            the instrument to operate on\n\n        params : dict with query parameters\n        \"\"\"\n        endpoint = self.ENDPOINT.format(instrument=instrument)\n        super(Instruments, self).__init__(endpoint, method=self.METHOD)\n\n\n@endpoint(\"v3/instruments/{instrument}/candles\")\nclass InstrumentsCandles(Instruments):\n    \"\"\"Get candle data for a specified Instrument.\"\"\"\n\n    @dyndoc_insert(responses)\n    def __init__(self, instrument, params=None):\n        \"\"\"Instantiate an InstrumentsCandles request.\n\n        Parameters\n        ----------\n        instrument : string (required)\n            the instrument to fetch candle data for\n\n        params : dict\n            optional request query parameters, check developer.oanda.com\n            for details\n\n\n        Params example::\n\n            {_v3_instruments_instrument_candles_params}\n\n\n        Candle data example::\n\n        >>> import oandapyV20\n        >>> import oandapyV20.endpoints.instruments as instruments\n        >>> client = oandapyV20.API(access_token=...)\n        >>> params = ...\n        >>> r = instruments.InstrumentsCandles(instrument=\"DE30_EUR\",\n        >>>                                    params=params)\n        >>> client.request(r)\n        >>> print r.response\n\n\n        Output::\n\n            {_v3_instruments_instrument_candles_resp}\n\n        \"\"\"\n        super(InstrumentsCandles, self).__init__(instrument)\n        self.params = params\n\n\n@endpoint(\"v3/instruments/{instrument}/orderBook\")\nclass InstrumentsOrderBook(Instruments):\n    \"\"\"Get orderbook data for a specified Instrument.\"\"\"\n\n    @dyndoc_insert(responses)\n    def __init__(self, instrument, params=None):\n        \"\"\"Instantiate an InstrumentsOrderBook request.\n\n        Parameters\n        ----------\n        instrument : string (required)\n            the instrument to fetch candle data for\n\n        params : dict\n            optional request query parameters, check developer.oanda.com\n            for details\n\n\n        Params example::\n\n            {_v3_instruments_instrument_orderbook_params}\n\n\n        OrderBook data example::\n\n        >>> import oandapyV20\n        >>> import oandapyV20.endpoints.instruments as instruments\n        >>> client = oandapyV20.API(access_token=...)\n        >>> params = ...\n        >>> r = instruments.InstrumentsOrderBook(instrument=\"EUR_USD\",\n        >>>                                      params=params)\n        >>> client.request(r)\n        >>> print r.response\n\n\n        Output::\n\n            {_v3_instruments_instrument_orderbook_resp}\n\n        \"\"\"\n        super(InstrumentsOrderBook, self).__init__(instrument)\n        self.params = params\n\n\n@endpoint(\"v3/instruments/{instrument}/positionBook\")\nclass InstrumentsPositionBook(Instruments):\n    \"\"\"Get positionbook data for a specified Instrument.\"\"\"\n\n    @dyndoc_insert(responses)\n    def __init__(self, instrument, params=None):\n        \"\"\"Instantiate an InstrumentsPositionBook request.\n\n        Parameters\n        ----------\n        instrument : string (required)\n            the instrument to fetch candle data for\n\n        params : dict\n            optional request query parameters, check developer.oanda.com\n            for details\n\n\n        Params example::\n\n            {_v3_instruments_instrument_positionbook_params}\n\n\n        PositionBook data example::\n\n        >>> import oandapyV20\n        >>> import oandapyV20.endpoints.instruments as instruments\n        >>> client = oandapyV20.API(access_token=...)\n        >>> params = ...\n        >>> r = instruments.InstrumentsPositionBook(instrument=\"EUR_USD\",\n        >>>                                         params=params)\n        >>> client.request(r)\n        >>> print r.response\n\n\n        Output::\n\n            {_v3_instruments_instrument_positionbook_resp}\n\n        \"\"\"\n        super(InstrumentsPositionBook, self).__init__(instrument)\n        self.params = params\n"
  },
  {
    "path": "oandapyV20/endpoints/orders.py",
    "content": "# -*- coding: utf-8 -*-\n\"\"\"Handle orders and pendingOrders endpoints.\"\"\"\nfrom .apirequest import APIRequest\nfrom .decorators import dyndoc_insert, endpoint\nfrom .responses.orders import responses\nfrom abc import abstractmethod\n\n\nclass Orders(APIRequest):\n    \"\"\"Orders - abstract base class to handle the orders endpoints.\"\"\"\n\n    ENDPOINT = \"\"\n    METHOD = \"GET\"\n    EXPECTED_STATUS = 0\n\n    @abstractmethod\n    @dyndoc_insert(responses)\n    def __init__(self, accountID, orderID=None):\n        \"\"\"Instantiate an Orders request.\n\n        Parameters\n        ----------\n        accountID : string (required)\n            id of the account to perform the request on.\n\n        orderID : string\n            id of the order to perform the request for.\n        \"\"\"\n        endpoint = self.ENDPOINT.format(accountID=accountID, orderID=orderID)\n        super(Orders, self).__init__(endpoint, method=self.METHOD,\n                                     expected_status=self.EXPECTED_STATUS)\n\n\n@endpoint(\"v3/accounts/{accountID}/orders\", \"POST\", 201)\nclass OrderCreate(Orders):\n    \"\"\"Create an Order for an Account.\"\"\"\n\n    HEADERS = {\"Content-Type\": \"application/json\"}\n\n    @dyndoc_insert(responses)\n    def __init__(self, accountID, data):\n        \"\"\"Instantiate an OrderCreate request.\n\n        Parameters\n        ----------\n        accountID : string (required)\n            id of the account to perform the request on.\n\n        data : JSON (required)\n            json orderbody to send\n\n\n        Orderbody example::\n\n            {_v3_accounts_accountID_orders_create_body}\n\n        >>> import oandapyV20\n        >>> import oandapyV20.endpoints.orders as orders\n        >>> client = oandapyV20.API(access_token=...)\n        >>> r = orders.OrderCreate(accountID, data=data)\n        >>> client.request(r)\n        >>> print r.response\n\n        ::\n\n            {_v3_accounts_accountID_orders_create_resp}\n\n        \"\"\"\n        super(OrderCreate, self).__init__(accountID)\n        self.data = data\n\n\n@endpoint(\"v3/accounts/{accountID}/orders\")\nclass OrderList(Orders):\n    \"\"\"Create an Order for an Account.\"\"\"\n\n    @dyndoc_insert(responses)\n    def __init__(self, accountID, params=None):\n        \"\"\"Instantiate an OrderList request.\n\n        Parameters\n        ----------\n        accountID : string (required)\n            id of the account to perform the request on.\n\n        params : dict\n            optional request query parameters, check developer.oanda.com\n            for details\n\n\n        Example::\n\n        >>> import oandapyV20\n        >>> import oandapyV20.endpoints.orders as orders\n        >>> client = oandapyV20.API(access_token=...)\n        >>> r = orders.OrderList(accountID)\n        >>> client.request(r)\n        >>> print r.response\n\n\n        Output::\n\n            {_v3_accounts_accountID_orders_list_resp}\n\n        \"\"\"\n        super(OrderList, self).__init__(accountID)\n        self.params = params\n\n\n@endpoint(\"v3/accounts/{accountID}/pendingOrders\")\nclass OrdersPending(Orders):\n    \"\"\"List all pending Orders in an Account.\"\"\"\n\n    @dyndoc_insert(responses)\n    def __init__(self, accountID):\n        \"\"\"Instantiate an OrdersPending request.\n\n        Parameters\n        ----------\n        accountID : string (required)\n            id of the account to perform the request on.\n\n\n        Example::\n\n        >>> import oandapyV20\n        >>> import oandapyV20.endpoints.orders as orders\n        >>> client = oandapyV20.API(access_token=...)\n        >>> r = orders.OrdersPending(accountID)\n        >>> client.request(r)\n        >>> print r.response\n\n\n        Output::\n\n            {_v3_accounts_accountID_orders_pending_resp}\n\n        \"\"\"\n        super(OrdersPending, self).__init__(accountID)\n\n\n@endpoint(\"v3/accounts/{accountID}/orders/{orderID}\")\nclass OrderDetails(Orders):\n    \"\"\"Get details for a single Order in an Account.\"\"\"\n\n    @dyndoc_insert(responses)\n    def __init__(self, accountID, orderID):\n        \"\"\"Instantiate an OrderDetails request.\n\n        Parameters\n        ----------\n        accountID : string (required)\n            id of the account to perform the request on.\n\n        orderID : string (required)\n            id of the order to perform the request on.\n\n\n        >>> import oandapyV20\n        >>> import oandapyV20.endpoints.orders as orders\n        >>> client = oandapyV20.API(access_token=...)\n        >>> r = orders.OrderDetails(accountID=..., orderID=...)\n        >>> client.request(r)\n        >>> print r.response\n\n        Output::\n\n            {_v3_accounts_accountID_order_details_resp}\n\n        \"\"\"\n        super(OrderDetails, self).__init__(accountID, orderID)\n\n\n@endpoint(\"v3/accounts/{accountID}/orders/{orderID}\", \"PUT\", 201)\nclass OrderReplace(Orders):\n    \"\"\"OrderReplace.\n\n    Replace an Order in an Account by simultaneously cancelling it and\n    creating a replacement Order.\n    \"\"\"\n\n    HEADERS = {\"Content-Type\": \"application/json\"}\n\n    @dyndoc_insert(responses)\n    def __init__(self, accountID, orderID, data):\n        \"\"\"Instantiate an OrderReplace request.\n\n        Parameters\n        ----------\n        accountID : string (required)\n            id of the account to perform the request on.\n\n        orderID : string (required)\n            id of the order to perform the request on.\n\n        data : JSON (required)\n            json orderbody to send\n\n\n        Orderbody example::\n\n            {_v3_accounts_accountID_order_replace_body}\n\n        >>> import oandapyV20\n        >>> import oandapyV20.endpoints.orders as orders\n        >>> client = oandapyV20.API(access_token=...)\n        >>> data = {_v3_accounts_accountID_order_replace_body}\n        >>> r = orders.OrderReplace(accountID=..., orderID=..., data=data)\n        >>> client.request(r)\n        >>> print r.response\n\n        Output::\n\n            {_v3_accounts_accountID_order_replace_resp}\n\n        \"\"\"\n        super(OrderReplace, self).__init__(accountID, orderID)\n        self.data = data\n\n\n@endpoint(\"v3/accounts/{accountID}/orders/{orderID}/cancel\", \"PUT\")\nclass OrderCancel(Orders):\n    \"\"\"Cancel a pending Order in an Account.\"\"\"\n\n    @dyndoc_insert(responses)\n    def __init__(self, accountID, orderID):\n        \"\"\"Instantiate an OrdersCancel request.\n\n        Parameters\n        ----------\n        accountID : string (required)\n            id of the account to perform the request on.\n\n        orderID : string (required)\n            id of the account to perform the request on.\n\n\n        Example::\n\n        >>> import oandapyV20\n        >>> import oandapyV20.endpoints.orders as orders\n        >>> client = oandapyV20.API(access_token=...)\n        >>> r = orders.OrderCancel(accountID= ..., orderID=...)\n        >>> client.request(r)\n        >>> print r.response\n\n\n        Output::\n\n            {_v3_accounts_accountID_order_cancel_resp}\n\n        \"\"\"\n        super(OrderCancel, self).__init__(accountID, orderID)\n\n\n@endpoint(\"v3/accounts/{accountID}/orders/{orderID}/clientExtensions\", \"PUT\")\nclass OrderClientExtensions(Orders):\n    \"\"\"Update the Client Extensions for an Order in an Account.\n\n    .. warning::\n        Do not set, modify or delete clientExtensions if your account\n        is associated with MT4.\n    \"\"\"\n\n    HEADERS = {\"Content-Type\": \"application/json\"}\n\n    @dyndoc_insert(responses)\n    def __init__(self, accountID, orderID, data):\n        \"\"\"Instantiate an OrderCreate request.\n\n        Parameters\n        ----------\n        accountID : string (required)\n            id of the account to perform the request on.\n\n        orderID : string (required)\n            id of the order to perform the request on.\n\n        data : JSON (required)\n            json orderbody to send\n\n\n        Orderbody example::\n\n            {_v3_accounts_accountID_order_clientextensions_body}\n\n        >>> import oandapyV20\n        >>> import oandapyV20.endpoints.orders as orders\n        >>> client = oandapyV20.API(access_token=...)\n        >>> r = orders.OrderClientExtensions(accountID, orderID, data=data)\n        >>> client.request(r)\n        >>> print r.response\n\n        ::\n\n            {_v3_accounts_accountID_order_clientextensions_resp}\n\n        \"\"\"\n        super(OrderClientExtensions, self).__init__(accountID, orderID)\n        self.data = data\n"
  },
  {
    "path": "oandapyV20/endpoints/positions.py",
    "content": "\"\"\"Handle position endpoints.\"\"\"\nfrom .apirequest import APIRequest\nfrom .decorators import dyndoc_insert, endpoint\nfrom .responses.positions import responses\nfrom abc import abstractmethod\n\n\nclass Positions(APIRequest):\n    \"\"\"Positions - abstractbase class to handle the 'positions' endpoints.\"\"\"\n\n    ENDPOINT = \"\"\n    METHOD = \"GET\"\n\n    @abstractmethod\n    @dyndoc_insert(responses)\n    def __init__(self, accountID, instrument=None):\n        \"\"\"Instantiate a Positions APIRequest instance.\n\n        Parameters\n        ----------\n        accountID : string (required)\n            the id of the account to perform the request on.\n\n        instrument : string (optional)\n            the instrument for the Positions request\n\n        \"\"\"\n        endpoint = self.ENDPOINT.format(accountID=accountID,\n                                        instrument=instrument)\n        super(Positions, self).__init__(endpoint,\n                                        method=self.METHOD)\n\n\n@endpoint(\"v3/accounts/{accountID}/positions\")\nclass PositionList(Positions):\n    \"\"\"PositionList.\n\n    List all Positions for an Account. The Positions returned are for every\n    instrument that has had a position during the lifetime of the Account.\n    \"\"\"\n\n    @dyndoc_insert(responses)\n    def __init__(self, accountID):\n        \"\"\"Instantiate a PositionList request.\n\n        Parameters\n        ----------\n        accountID : string (required)\n            id of the account to perform the request on.\n\n\n        >>> import oandapyV20\n        >>> import oandapyV20.endpoints.positions as positions\n        >>> accountID = ...\n        >>> client = oandapyV20.API(access_token=...)\n        >>> r = positions.PositionList(accountID=accountID)\n        >>> client.request(r)\n        >>> print r.response\n\n        Output::\n\n            {_v3_accounts_accountID_positions_resp}\n\n        \"\"\"\n        super(PositionList, self).__init__(accountID)\n\n\n@endpoint(\"v3/accounts/{accountID}/openPositions\")\nclass OpenPositions(Positions):\n    \"\"\"OpenPositions.\n\n    List all open Positions for an Account. An open Position is a Position\n    in an Account that currently has a Trade opened for it.\n    \"\"\"\n\n    @dyndoc_insert(responses)\n    def __init__(self, accountID):\n        \"\"\"Instantiate an OpenPositions request.\n\n        Parameters\n        ----------\n        accountID : string (required)\n            id of the account to perform the request on.\n\n\n        >>> import oandapyV20\n        >>> import oandapyV20.endpoints.positions as positions\n        >>> accountID = ...\n        >>> client = oandapyV20.API(access_token=...)\n        >>> r = positions.OpenPositions(accountID=accountID)\n        >>> client.request(r)\n        >>> print r.response\n\n        Output::\n\n            {_v3_accounts_accountID_openpositions_resp}\n\n        \"\"\"\n        super(OpenPositions, self).__init__(accountID)\n\n\n@endpoint(\"v3/accounts/{accountID}/positions/{instrument}\")\nclass PositionDetails(Positions):\n    \"\"\"PositionDetails.\n\n    Get the details of a single instrument's position in an Account. The\n    position may be open or not.\n    \"\"\"\n\n    @dyndoc_insert(responses)\n    def __init__(self, accountID, instrument):\n        \"\"\"Instantiate a PositionDetails request.\n\n        Parameters\n        ----------\n        accountID : string (required)\n            id of the account to perform the request on.\n\n        instrument : string (required)\n            id of the instrument to get the position details for.\n\n\n        >>> import oandapyV20\n        >>> import oandapyV20.endpoints.positions as positions\n        >>> accountID = ...\n        >>> instrument = ...\n        >>> client = oandapyV20.API(access_token=...)\n        >>> r = positions.PositionDetails(accountID=accountID, instrument)\n        >>> client.request(r)\n        >>> print r.response\n\n        Output::\n\n            {_v3_accounts_accountID_positiondetails_resp}\n\n        \"\"\"\n        super(PositionDetails, self).__init__(accountID, instrument)\n\n\n@endpoint(\"v3/accounts/{accountID}/positions/{instrument}/close\", \"PUT\")\nclass PositionClose(Positions):\n    \"\"\"Closeout the open Position regarding instrument in an Account.\"\"\"\n\n    HEADERS = {\"Content-Type\": \"application/json\"}\n\n    @dyndoc_insert(responses)\n    def __init__(self, accountID, instrument, data):\n        \"\"\"Instantiate a PositionClose request.\n\n        Parameters\n        ----------\n        accountID : string (required)\n            id of the account to perform the request on.\n\n        instrument : string (required)\n            instrument to close partially or fully.\n\n        data : dict (required)\n            closeout specification data to send, check developer.oanda.com\n            for details.\n\n\n        Data body example::\n\n            {_v3_accounts_accountID_position_close_body}\n\n\n        >>> import oandapyV20\n        >>> import oandapyV20.endpoints.positions as positions\n        >>> accountID = ...\n        >>> instrument = ...\n        >>> client = oandapyV20.API(access_token=...)\n        >>> data = {_v3_accounts_accountID_position_close_body}\n        >>> r = positions.PositionClose(accountID=accountID,\n        >>>                             instrument=instrument,\n        >>>                             data=data)\n        >>> client.request(r)\n        >>> print r.response\n\n        Output::\n\n            {_v3_accounts_accountID_position_close_resp}\n\n        \"\"\"\n        super(PositionClose, self).__init__(accountID, instrument)\n        self.data = data\n"
  },
  {
    "path": "oandapyV20/endpoints/pricing.py",
    "content": "# -*- coding: utf-8 -*-\n\"\"\"Handle pricing endpoints.\"\"\"\nfrom .apirequest import APIRequest\nfrom ..exceptions import StreamTerminated\nfrom .decorators import dyndoc_insert, endpoint\nfrom .responses.pricing import responses\nfrom types import GeneratorType\nfrom abc import abstractmethod\n\n\nclass Pricing(APIRequest):\n    \"\"\"Pricing - class to handle pricing endpoint.\"\"\"\n\n    ENDPOINT = \"\"\n    METHOD = \"GET\"\n\n    @abstractmethod\n    def __init__(self, accountID):\n        \"\"\"Instantiate a Pricing APIRequest instance.\n\n        Parameters\n        ----------\n        accountID : string (required)\n            the accountID of the account.\n\n        \"\"\"\n        endpoint = self.ENDPOINT.format(accountID=accountID)\n        super(Pricing, self).__init__(endpoint, method=self.METHOD)\n\n\n@endpoint(\"v3/accounts/{accountID}/pricing\")\nclass PricingInfo(Pricing):\n    \"\"\"Pricing.\n\n    Get pricing information for a specified list of Instruments within\n    an account.\n    \"\"\"\n\n    @dyndoc_insert(responses)\n    def __init__(self, accountID, params=None):\n        \"\"\"Instantiate a PricingStream APIRequest instance.\n\n        Parameters\n        ----------\n        accountID : string (required)\n            the accountID of the account.\n\n        params : dict (required)\n            parameters for the request, check developer.oanda.com for details.\n\n        Example\n        -------\n\n        >>> import oandapyV20\n        >>> from oandapyV20 import API\n        >>> import oandapyV20.endpoints.pricing as pricing\n        >>> accountID = \"...\"\n        >>> api = API(access_token=\"...\")\n        >>> params = {_v3_accounts_accountID_pricing_params}\n        >>> r = pricing.PricingInfo(accountID=accountID, params=params)\n        >>> rv = api.request(r)\n        >>> print r.response\n\n        Output::\n\n\n           {_v3_accounts_accountID_pricing_resp}\n\n\n        \"\"\"\n        super(PricingInfo, self).__init__(accountID)\n        self.params = params\n\n\n@endpoint(\"v3/accounts/{accountID}/pricing/stream\")\nclass PricingStream(Pricing):\n    \"\"\"PricingStream.\n\n    Get realtime pricing information for a specified list of Instruments.\n\n    \"\"\"\n\n    STREAM = True\n\n    @dyndoc_insert(responses)\n    def __init__(self, accountID, params=None):\n        \"\"\"Instantiate a PricingStream APIRequest instance.\n\n        Parameters\n        ----------\n        accountID : string (required)\n            the accountID of the account.\n\n        params : dict (required)\n            parameters for the request, check developer.oanda.com for details.\n\n        Example\n        -------\n\n        >>> import oandapyV20\n        >>> from oandapyV20 import API\n        >>> import oandapyV20.endpoints.pricing as pricing\n        >>> accountID = \"...\"\n        >>> api = API(access_token=\"...\")\n        >>> params = {_v3_accounts_accountID_pricing_stream_params}\n        >>> r = pricing.PricingStream(accountID=accountID, params=params)\n        >>> rv = api.request(r)\n        >>> maxrecs = 100\n        >>> for ticks in r:\n        >>>     print json.dumps(R, indent=4),\",\"\n        >>>     if maxrecs == 0:\n        >>>         r.terminate(\"maxrecs records received\")\n\n        Output::\n\n           {_v3_accounts_accountID_pricing_stream_ciresp}\n\n        \"\"\"\n        super(PricingStream, self).__init__(accountID)\n        self.params = params\n\n    def terminate(self, message=\"\"):\n        \"\"\"terminate the stream.\n\n        Calling this method will stop the generator yielding tickrecords.\n        A message can be passed optionally.\n        \"\"\"\n        if not isinstance(self.response, GeneratorType):\n            raise ValueError(\"request does not contain a stream response\")\n\n        self.response.throw(StreamTerminated(message))\n"
  },
  {
    "path": "oandapyV20/endpoints/responses/__init__.py",
    "content": ""
  },
  {
    "path": "oandapyV20/endpoints/responses/accounts.py",
    "content": "\"\"\"Responses.\n\nresponses serve both testing purpose aswell as dynamic docstring replacement\n\"\"\"\nresponses = {\n    \"_v3_accounts\": {\n        \"url\": \"/v3/accounts\",\n        \"response\": {\n            \"accounts\": [\n                {\n                  \"id\": \"101-004-1435156-002\",\n                  \"tags\": []\n                },\n                {\n                  \"id\": \"101-004-1435156-001\",\n                  \"tags\": []\n                }\n            ]\n            },\n        },\n    \"_v3_account_by_accountID\": {\n        \"url\": \"/v3/accounts/{}\",\n        \"response\": {\n            \"account\": {\n                \"trades\": [\n                    {\n                        \"instrument\": \"DE30_EUR\",\n                        \"financing\": \"0.0000\",\n                        \"openTime\": \"2016-07-12T09:32:18.062823776Z\",\n                        \"initialUnits\": \"-10\",\n                        \"currentUnits\": \"-10\",\n                        \"price\": \"9984.7\",\n                        \"unrealizedPL\": \"341.0000\",\n                        \"realizedPL\": \"0.0000\",\n                        \"state\": \"OPEN\",\n                        \"id\": \"821\"\n                    },\n                    {\n                        \"instrument\": \"DE30_EUR\",\n                        \"financing\": \"0.0000\",\n                        \"openTime\": \"2016-07-12T09:32:18.206929733Z\",\n                        \"initialUnits\": \"-10\",\n                        \"currentUnits\": \"-10\",\n                        \"price\": \"9984.7\",\n                        \"unrealizedPL\": \"341.0000\",\n                        \"realizedPL\": \"0.0000\",\n                        \"state\": \"OPEN\",\n                        \"id\": \"823\"\n                    }\n                ],\n                \"marginCloseoutNAV\": \"49393.6580\",\n                \"marginUsed\": \"9948.9000\",\n                \"currency\": \"EUR\",\n                \"resettablePL\": \"-1301.0046\",\n                \"NAV\": \"49377.6580\",\n                \"marginCloseoutMarginUsed\": \"9949.8000\",\n                \"id\": \"101-004-1435156-001\",\n                \"marginCloseoutPositionValue\": \"198996.0000\",\n                \"openTradeCount\": 2,\n                \"orders\": [\n                    {\n                        \"partialFill\": \"DEFAULT_FILL\",\n                        \"price\": \"0.87000\",\n                        \"stopLossOnFill\": {\n                            \"timeInForce\": \"GTC\",\n                            \"price\": \"0.88000\"\n                        },\n                        \"timeInForce\": \"GTC\",\n                        \"clientExtensions\": {\n                            \"comment\": \"myComment\",\n                            \"id\": \"myID\"\n                        },\n                        \"id\": \"204\",\n                        \"triggerCondition\": \"TRIGGER_DEFAULT\",\n                        \"replacesOrderID\": \"200\",\n                        \"positionFill\": \"POSITION_DEFAULT\",\n                        \"createTime\": \"2016-07-08T07:18:47.623211321Z\",\n                        \"instrument\": \"EUR_GBP\",\n                        \"state\": \"PENDING\",\n                        \"units\": \"-50000\",\n                        \"type\": \"LIMIT\"\n                    }\n                ],\n                \"hedgingEnabled\": False,\n                \"marginCloseoutPercent\": \"0.10072\",\n                \"marginCallMarginUsed\": \"9949.8000\",\n                \"openPositionCount\": 1,\n                \"positionValue\": \"198978.0000\",\n                \"pl\": \"-1301.0046\",\n                \"lastTransactionID\": \"833\",\n                \"marginAvailable\": \"39428.7580\",\n                \"marginCloseoutUnrealizedPL\": \"698.0000\",\n                \"marginRate\": \"0.05\",\n                \"marginCallPercent\": \"0.20144\",\n                \"pendingOrderCount\": 1,\n                \"withdrawalLimit\": \"39428.7580\",\n                \"unrealizedPL\": \"682.0000\",\n                \"alias\": \"hootnotv20\",\n                \"createdByUserID\": 1435156,\n                \"positions\": [\n                    {\n                        \"short\": {\n                            \"units\": \"0\",\n                            \"resettablePL\": \"0.0000\",\n                            \"unrealizedPL\": \"0.0000\",\n                            \"pl\": \"0.0000\"\n                        },\n                        \"unrealizedPL\": \"0.0000\",\n                        \"long\": {\n                            \"units\": \"0\",\n                            \"resettablePL\": \"-3.8046\",\n                            \"unrealizedPL\": \"0.0000\",\n                            \"pl\": \"-3.8046\"\n                        },\n                        \"instrument\": \"EUR_USD\",\n                        \"resettablePL\": \"-3.8046\",\n                        \"pl\": \"-3.8046\"\n                    },\n                    {\n                        \"short\": {\n                            \"unrealizedPL\": \"682.0000\",\n                            \"tradeIDs\": [\n                                \"821\",\n                                \"823\"\n                            ],\n                            \"resettablePL\": \"-1744.8000\",\n                            \"units\": \"-20\",\n                            \"averagePrice\": \"9984.7\",\n                            \"pl\": \"-1744.8000\"\n                        },\n                        \"unrealizedPL\": \"682.0000\",\n                        \"long\": {\n                            \"units\": \"0\",\n                            \"resettablePL\": \"447.6000\",\n                            \"unrealizedPL\": \"0.0000\",\n                            \"pl\": \"447.6000\"\n                        },\n                        \"instrument\": \"DE30_EUR\",\n                        \"resettablePL\": \"-1297.2000\",\n                        \"pl\": \"-1297.2000\"\n                    }\n                ],\n                \"createdTime\": \"2016-06-24T21:03:50.914647476Z\",\n                \"balance\": \"48695.6580\"\n            },\n            \"lastTransactionID\": \"833\"\n        }\n    },\n    \"_v3_account_by_accountID_summary\": {\n        \"url\": \"v3/accounts/{accountID}/summary\",\n        \"response\": {\n            \"account\": {\n                \"marginCloseoutNAV\": \"35454.4740\",\n                \"marginUsed\": \"10581.5000\",\n                \"currency\": \"EUR\",\n                \"resettablePL\": \"-13840.3525\",\n                \"NAV\": \"35454.4740\",\n                \"marginCloseoutMarginUsed\": \"10581.5000\",\n                \"marginCloseoutPositionValue\": \"211630.0000\",\n                \"openTradeCount\": 2,\n                \"id\": \"101-004-1435156-001\",\n                \"openPositionCount\": 1,\n                \"marginCloseoutPercent\": \"0.14923\",\n                \"marginCallMarginUsed\": \"10581.5000\",\n                \"hedgingEnabled\": False,\n                \"positionValue\": \"211630.0000\",\n                \"pl\": \"-13840.3525\",\n                \"lastTransactionID\": \"2123\",\n                \"marginAvailable\": \"24872.9740\",\n                \"marginRate\": \"0.05\",\n                \"marginCallPercent\": \"0.29845\",\n                \"pendingOrderCount\": 0,\n                \"withdrawalLimit\": \"24872.9740\",\n                \"unrealizedPL\": \"0.0000\",\n                \"alias\": \"hootnotv20\",\n                \"createdByUserID\": 1435156,\n                \"marginCloseoutUnrealizedPL\": \"0.0000\",\n                \"createdTime\": \"2016-06-24T21:03:50.914647476Z\",\n                \"balance\": \"35454.4740\"\n            },\n            \"lastTransactionID\": \"2123\"\n        }\n    },\n    \"_v3_account_by_accountID_instruments\": {\n        \"url\": \"/v3/accounts/{accountID}/instuments\",\n        \"params\": {\n            \"instruments\": \"EU50_EUR,EUR_USD,US30_USD,\"\n                           \"FR40_EUR,EUR_CHF,DE30_EUR\"\n        },\n        \"response\": {\n            \"instruments\": [\n                {\n                    \"minimumTradeSize\": \"1\",\n                    \"displayName\": \"Europe 50\",\n                    \"name\": \"EU50_EUR\",\n                    \"displayPrecision\": 1,\n                    \"type\": \"CFD\",\n                    \"minimumTrailingStopDistance\": \"5.0\",\n                    \"marginRate\": \"0.05\",\n                    \"maximumOrderUnits\": \"3000\",\n                    \"tradeUnitsPrecision\": 0,\n                    \"pipLocation\": 0,\n                    \"maximumPositionSize\": \"0\",\n                    \"maximumTrailingStopDistance\": \"10000.0\"\n                },\n                {\n                    \"minimumTradeSize\": \"1\",\n                    \"displayName\": \"EUR/USD\",\n                    \"name\": \"EUR_USD\",\n                    \"displayPrecision\": 5,\n                    \"type\": \"CURRENCY\",\n                    \"minimumTrailingStopDistance\": \"0.00050\",\n                    \"marginRate\": \"0.05\",\n                    \"maximumOrderUnits\": \"100000000\",\n                    \"tradeUnitsPrecision\": 0,\n                    \"pipLocation\": -4,\n                    \"maximumPositionSize\": \"0\",\n                    \"maximumTrailingStopDistance\": \"1.00000\"\n                },\n                {\n                    \"minimumTradeSize\": \"1\",\n                    \"displayName\": \"US Wall St 30\",\n                    \"name\": \"US30_USD\",\n                    \"displayPrecision\": 1,\n                    \"type\": \"CFD\",\n                    \"minimumTrailingStopDistance\": \"5.0\",\n                    \"marginRate\": \"0.05\",\n                    \"maximumOrderUnits\": \"1000\",\n                    \"tradeUnitsPrecision\": 0,\n                    \"pipLocation\": 0,\n                    \"maximumPositionSize\": \"0\",\n                    \"maximumTrailingStopDistance\": \"10000.0\"\n                },\n                {\n                    \"minimumTradeSize\": \"1\",\n                    \"displayName\": \"France 40\",\n                    \"name\": \"FR40_EUR\",\n                    \"displayPrecision\": 1,\n                    \"type\": \"CFD\",\n                    \"minimumTrailingStopDistance\": \"5.0\",\n                    \"marginRate\": \"0.05\",\n                    \"maximumOrderUnits\": \"2000\",\n                    \"tradeUnitsPrecision\": 0,\n                    \"pipLocation\": 0,\n                    \"maximumPositionSize\": \"0\",\n                    \"maximumTrailingStopDistance\": \"10000.0\"\n                },\n                {\n                    \"minimumTradeSize\": \"1\",\n                    \"displayName\": \"EUR/CHF\",\n                    \"name\": \"EUR_CHF\",\n                    \"displayPrecision\": 5,\n                    \"type\": \"CURRENCY\",\n                    \"minimumTrailingStopDistance\": \"0.00050\",\n                    \"marginRate\": \"0.05\",\n                    \"maximumOrderUnits\": \"100000000\",\n                    \"tradeUnitsPrecision\": 0,\n                    \"pipLocation\": -4,\n                    \"maximumPositionSize\": \"0\",\n                    \"maximumTrailingStopDistance\": \"1.00000\"\n                },\n                {\n                    \"minimumTradeSize\": \"1\",\n                    \"displayName\": \"Germany 30\",\n                    \"name\": \"DE30_EUR\",\n                    \"displayPrecision\": 1,\n                    \"type\": \"CFD\",\n                    \"minimumTrailingStopDistance\": \"5.0\",\n                    \"marginRate\": \"0.05\",\n                    \"maximumOrderUnits\": \"2500\",\n                    \"tradeUnitsPrecision\": 0,\n                    \"pipLocation\": 0,\n                    \"maximumPositionSize\": \"0\",\n                    \"maximumTrailingStopDistance\": \"10000.0\"\n                },\n            ],\n            \"lastTransactionID\": \"2124\"\n        },\n    },\n    \"_v3_accounts_accountID_account_config\": {\n        \"url\": \"/v3/accounts/{accountID}/configuration\",\n        \"body\": {\n            \"marginRate\": \"0.05\"\n        },\n        \"response\": {\n            \"lastTransactionID\": \"830\",\n            \"clientConfigureTransaction\": {\n                \"userID\": 1435156,\n                \"marginRate\": \"0.05\",\n                \"batchID\": \"830\",\n                \"time\": \"2016-07-12T19:48:11.657494168Z\",\n                \"type\": \"CLIENT_CONFIGURE\",\n                \"id\": \"830\",\n                \"accountID\": \"101-004-1435156-001\"\n            }\n        },\n    },\n    \"_v3_accounts_accountID_account_changes\": {\n        \"url\": \"/v3/accounts/{accountID}/changes\",\n        \"params\": {\n            \"sinceTransactionID\": 2308\n        },\n        \"response\": {\n            \"state\": {\n                \"trades\": [],\n                \"marginCloseoutNAV\": \"33848.2663\",\n                \"unrealizedPL\": \"0.0000\",\n                \"marginUsed\": \"0.0000\",\n                \"marginAvailable\": \"33848.2663\",\n                \"positions\": [],\n                \"marginCloseoutUnrealizedPL\": \"0.0000\",\n                \"marginCallMarginUsed\": \"0.0000\",\n                \"marginCallPercent\": \"0.00000\",\n                \"marginCloseoutPercent\": \"0.00000\",\n                \"NAV\": \"33848.2663\",\n                \"marginCloseoutMarginUsed\": \"0.0000\",\n                \"positionValue\": \"0.0000\",\n                \"orders\": [],\n                \"withdrawalLimit\": \"33848.2663\"\n            },\n            \"changes\": {\n                \"tradesReduced\": [],\n                \"tradesOpened\": [],\n                \"ordersFilled\": [],\n                \"transactions\": [\n                  {\n                    \"timeInForce\": \"GTC\",\n                    \"triggerCondition\": \"TRIGGER_DEFAULT\",\n                    \"positionFill\": \"DEFAULT\",\n                    \"stopLossOnFill\": {\n                      \"timeInForce\": \"GTC\",\n                      \"price\": \"1.22000\"\n                    },\n                    \"userID\": 1435156,\n                    \"id\": \"2309\",\n                    \"batchID\": \"2309\",\n                    \"instrument\": \"EUR_USD\",\n                    \"reason\": \"CLIENT_ORDER\",\n                    \"time\": \"2016-10-25T21:07:21.065554321Z\",\n                    \"units\": \"-100\",\n                    \"type\": \"LIMIT_ORDER\",\n                    \"price\": \"1.20000\",\n                    \"accountID\": \"101-004-1435156-001\"\n                  }\n                ],\n                \"ordersCreated\": [\n                  {\n                    \"triggerCondition\": \"TRIGGER_DEFAULT\",\n                    \"partialFill\": \"DEFAULT_FILL\",\n                    \"price\": \"1.20000\",\n                    \"stopLossOnFill\": {\n                      \"timeInForce\": \"GTC\",\n                      \"price\": \"1.22000\"\n                    },\n                    \"createTime\": \"2016-10-25T21:07:21.065554321Z\",\n                    \"timeInForce\": \"GTC\",\n                    \"instrument\": \"EUR_USD\",\n                    \"state\": \"PENDING\",\n                    \"units\": \"-100\",\n                    \"id\": \"2309\",\n                    \"type\": \"LIMIT\",\n                    \"positionFill\": \"POSITION_DEFAULT\"\n                  }\n                ],\n                \"positions\": [],\n                \"ordersTriggered\": [],\n                \"ordersCancelled\": [],\n                \"tradesClosed\": []\n            },\n            \"lastTransactionID\": \"2309\"\n        }\n    }\n}\n"
  },
  {
    "path": "oandapyV20/endpoints/responses/forexlabs.py",
    "content": "\"\"\"Responses.\n\nresponses serve both testing purpose aswell as dynamic docstring replacement\n\"\"\"\n\nresponses = {\n    \"_v3_forexlabs_calendar\": {\n        \"url\": \"labs/v1/calendar\",\n        \"params\": {\n            \"period\": 86400,\n            \"instrument\": \"EUR_USD\"\n        },\n        \"response\": [\n              {\n                \"impact\": 3,\n                \"actual\": \"60.8\",\n                \"title\": \"ISM Manufacturing\",\n                \"timestamp\": 1519916400,\n                \"region\": \"americas\",\n                \"forecast\": \"59.5\",\n                \"currency\": \"USD\",\n                \"unit\": \"index\",\n                \"market\": \"58.7\",\n                \"previous\": \"59.1\"\n              }\n        ]\n    },\n    \"_v3_forexlabs_histposratios\": {\n        \"url\": \"labs/v1/historical_position_ratios\",\n        \"params\": {\n            \"period\": 86400,\n            \"instrument\": \"EUR_USD\"\n        },\n        \"response\": {\n              \"data\": {\n                \"EUR_USD\": {\n                  \"data\": [\n                    [\n                      1519924801,\n                      44.22,\n                      1.2209\n                    ],\n                    [\n                      1519926001,\n                      44.33,\n                      1.221\n                    ],\n                    [\n                      1519927200,\n                      44.16,\n                      1.2212\n                    ],\n                    [\n                      1519928400,\n                      44.2,\n                      1.2209\n                    ],\n                    [\n                      1519929601,\n                      43.88,\n                      1.2201\n                    ],\n                    [\n                      1519930800,\n                      44.15,\n                      1.2197\n                    ],\n                    [\n                      1519932000,\n                      44.51,\n                      1.2204\n                    ],\n                    [\n                      1519933200,\n                      44.55,\n                      1.2233\n                    ],\n                    [\n                      1519934401,\n                      44.55,\n                      1.2254\n                    ],\n                    [\n                      1519935601,\n                      44.08,\n                      1.226\n                    ],\n                    [\n                      1519936801,\n                      43.67,\n                      1.2264\n                    ],\n                    [\n                      1519938001,\n                      43.55,\n                      1.2263\n                    ],\n                    [\n                      1519939201,\n                      43.25,\n                      1.2261\n                    ],\n                    [\n                      1519940401,\n                      43.28,\n                      1.2263\n                    ],\n                    [\n                      1519941601,\n                      43.39,\n                      1.2267\n                    ],\n                    [\n                      1519942801,\n                      43.69,\n                      1.227\n                    ],\n                    [\n                      1519944001,\n                      43.57,\n                      1.2269\n                    ],\n                    [\n                      1519945201,\n                      43.68,\n                      1.2272\n                    ],\n                    [\n                      1519946400,\n                      43.51,\n                      1.2268\n                    ],\n                    [\n                      1519947601,\n                      43.53,\n                      1.2267\n                    ],\n                    [\n                      1519948801,\n                      43.71,\n                      1.2271\n                    ],\n                    [\n                      1519950001,\n                      43.66,\n                      1.2265\n                    ],\n                    [\n                      1519951201,\n                      43.78,\n                      1.2269\n                    ],\n                    [\n                      1519952401,\n                      43.86,\n                      1.2273\n                    ],\n                    [\n                      1519953600,\n                      43.85,\n                      1.2273\n                    ],\n                    [\n                      1519954800,\n                      43.81,\n                      1.2271\n                    ],\n                    [\n                      1519956001,\n                      44,\n                      1.2275\n                    ],\n                    [\n                      1519957200,\n                      43.89,\n                      1.2274\n                    ],\n                    [\n                      1519958401,\n                      43.95,\n                      1.2273\n                    ],\n                    [\n                      1519959601,\n                      43.93,\n                      1.2273\n                    ],\n                    [\n                      1519960800,\n                      43.86,\n                      1.2276\n                    ],\n                    [\n                      1519962000,\n                      44.02,\n                      1.2278\n                    ],\n                    [\n                      1519963200,\n                      44.18,\n                      1.228\n                    ],\n                    [\n                      1519964401,\n                      44.52,\n                      1.2283\n                    ],\n                    [\n                      1519965600,\n                      44.19,\n                      1.2281\n                    ],\n                    [\n                      1519966801,\n                      44.14,\n                      1.2278\n                    ],\n                    [\n                      1519968000,\n                      43.93,\n                      1.2276\n                    ],\n                    [\n                      1519969201,\n                      43.82,\n                      1.2277\n                    ],\n                    [\n                      1519970401,\n                      43.77,\n                      1.2279\n                    ],\n                    [\n                      1519971601,\n                      43.02,\n                      1.2269\n                    ],\n                    [\n                      1519972801,\n                      42.99,\n                      1.2265\n                    ],\n                    [\n                      1519974001,\n                      42.73,\n                      1.2263\n                    ],\n                    [\n                      1519975201,\n                      42.22,\n                      1.2262\n                    ],\n                    [\n                      1519976400,\n                      42.13,\n                      1.2255\n                    ],\n                    [\n                      1519977601,\n                      42.02,\n                      1.2263\n                    ],\n                    [\n                      1519978801,\n                      42.15,\n                      1.2261\n                    ],\n                    [\n                      1519980000,\n                      42.5,\n                      1.2273\n                    ],\n                    [\n                      1519981201,\n                      42.2,\n                      1.2274\n                    ],\n                    [\n                      1519982400,\n                      42.06,\n                      1.2271\n                    ],\n                    [\n                      1519983600,\n                      42.38,\n                      1.2279\n                    ],\n                    [\n                      1519984800,\n                      42.29,\n                      1.2276\n                    ],\n                    [\n                      1519986000,\n                      42.16,\n                      1.2281\n                    ],\n                    [\n                      1519987201,\n                      43.46,\n                      1.2291\n                    ],\n                    [\n                      1519988401,\n                      43.51,\n                      1.2291\n                    ],\n                    [\n                      1519989601,\n                      43.4,\n                      1.2317\n                    ],\n                    [\n                      1519990800,\n                      43.46,\n                      1.2317\n                    ],\n                    [\n                      1519992001,\n                      43.07,\n                      1.2304\n                    ],\n                    [\n                      1519993201,\n                      43.56,\n                      1.2316\n                    ],\n                    [\n                      1519994401,\n                      43.75,\n                      1.2319\n                    ],\n                    [\n                      1519995601,\n                      43.15,\n                      1.2308\n                    ],\n                    [\n                      1519996801,\n                      42.94,\n                      1.2309\n                    ],\n                    [\n                      1519998001,\n                      42.99,\n                      1.2315\n                    ],\n                    [\n                      1519999201,\n                      42.33,\n                      1.2309\n                    ],\n                    [\n                      1520000400,\n                      41.93,\n                      1.2299\n                    ],\n                    [\n                      1520001601,\n                      42.31,\n                      1.2303\n                    ],\n                    [\n                      1520002801,\n                      42.5,\n                      1.2313\n                    ],\n                    [\n                      1520004000,\n                      42.8,\n                      1.2326\n                    ],\n                    [\n                      1520005201,\n                      42.67,\n                      1.2317\n                    ],\n                    [\n                      1520006401,\n                      42.29,\n                      1.2309\n                    ],\n                    [\n                      1520007600,\n                      42.33,\n                      1.2309\n                    ],\n                    [\n                      1520008800,\n                      42.63,\n                      1.2321\n                    ],\n                    [\n                      1520010001,\n                      42.11,\n                      1.2314\n                    ]\n                  ],\n                  \"label\": \"EUR/USD\"\n                }\n              }\n            }\n    },\n    \"_v3_forexlabs_spreads\": {\n        \"url\": \"labs/v1/spreads\",\n        \"params\": {\n            \"period\": 57600,\n            \"instrument\": \"EUR_USD\"\n        },\n        \"response\": {\n              \"max\": [\n                [\n                  1520028000,\n                  6\n                ]\n              ],\n              \"avg\": [\n                [\n                  1520028000,\n                  3.01822\n                ]\n              ],\n              \"min\": [\n                [\n                  1520028000,\n                  1.7\n                ]\n              ]\n        }\n    },\n    \"_v3_forexlabs_commoftrad\": {\n        \"url\": \"labs/v1/commitments_of_traders\",\n        \"params\": {\n            \"instrument\": \"EUR_USD\"\n        },\n        \"response\": {\n            \"EUR_USD\": [\n                {\n                  \"oi\": \"603460\",\n                  \"price\": \"1.2315925\",\n                  \"ncs\": \"109280\",\n                  \"ncl\": \"258022\",\n                  \"date\": 1517288400,\n                  \"unit\": \"Contracts Of EUR 125,000\"\n                },\n                {\n                  \"oi\": \"596937\",\n                  \"price\": \"1.2364\",\n                  \"ncs\": \"110546\",\n                  \"ncl\": \"251369\",\n                  \"date\": 1517893200,\n                  \"unit\": \"Contracts Of EUR 125,000\"\n                },\n                {\n                  \"oi\": \"564233\",\n                  \"price\": \"1.2330275\",\n                  \"ncs\": \"103496\",\n                  \"ncl\": \"230785\",\n                  \"date\": 1518498000,\n                  \"unit\": \"Contracts Of EUR 125,000\"\n                },\n                {\n                  \"oi\": \"567534\",\n                  \"price\": \"1.2346025\",\n                  \"ncs\": \"103147\",\n                  \"ncl\": \"229273\",\n                  \"date\": 1519102800,\n                  \"unit\": \"Contracts Of EUR 125,000\"\n                },\n                {\n                  \"oi\": \"567463\",\n                  \"price\": \"1.23557\",\n                  \"ncs\": \"100310\",\n                  \"ncl\": \"238287\",\n                  \"date\": 1519707600,\n                  \"unit\": \"Contracts Of EUR 125,000\"\n                }\n            ]\n        }\n    },\n    \"_v3_forexlabs_orderbookdata\": {\n        \"url\": \"labs/v1/orderbook_data\",\n        \"params\": {\n            \"instrument\": \"EUR_USD\",\n            \"period\": 3600\n        },\n        \"response\": {\n            \"1520066400\": {\n                \"rate\": 1.2318,\n                \"price_points\": {\n                  \"1.288\": {\n                    \"ps\": 0,\n                    \"ol\": 0.0105,\n                    \"os\": 0.0105,\n                    \"pl\": 0\n                  },\n                  \"1.23\": {\n                    \"ps\": 1.2155,\n                    \"ol\": 0.3871,\n                    \"os\": 0.2615,\n                    \"pl\": 0.5633\n                  },\n                  \"1.223\": {\n                    \"ps\": 1.1266,\n                    \"ol\": 0.5021,\n                    \"os\": 0.2197,\n                    \"pl\": 0.3854\n                  },\n                  \"1.1825\": {\n                    \"ps\": 0.1779,\n                    \"ol\": 0.1465,\n                    \"os\": 0.0628,\n                    \"pl\": 0\n                  },\n                  \"1.22\": {\n                    \"ps\": 0.9191,\n                    \"ol\": 0.6486,\n                    \"os\": 0.136,\n                    \"pl\": 0.2965\n                  },\n                  \"1.2245\": {\n                    \"ps\": 0.5336,\n                    \"ol\": 0.5021,\n                    \"os\": 0.3975,\n                    \"pl\": 0.4447\n                  },\n                  \"1.2085\": {\n                    \"ps\": 0.1482,\n                    \"ol\": 0.2092,\n                    \"os\": 0.2197,\n                    \"pl\": 0.1482\n                  },\n                  \"1.26\": {\n                    \"ps\": 0,\n                    \"ol\": 0.2197,\n                    \"os\": 0.68,\n                    \"pl\": 0\n                  },\n                  \"1.25\": {\n                    \"ps\": 0.0593,\n                    \"ol\": 0.272,\n                    \"os\": 1.0566,\n                    \"pl\": 0.1186\n                  },\n                  \"1.24\": {\n                    \"ps\": 0.1186,\n                    \"ol\": 0.4289,\n                    \"os\": 0.8264,\n                    \"pl\": 0.4447\n                  }\n                }\n            }\n        }\n    },\n    \"_v3_forexlabs_autochartist\": {\n        \"url\": \"labs/v1/signal/autochartist\",\n        \"params\": {\n            \"instrument\": \"EUR_JPY\"\n        },\n        \"response\": {\n              \"signals\": [\n                {\n                  \"type\": \"chartpattern\",\n                  \"meta\": {\n                    \"direction\": 1,\n                    \"probability\": 72.36,\n                    \"pattern\": \"Channel Down\",\n                    \"historicalstats\": {\n                      \"hourofday\": {\n                        \"total\": 1909,\n                        \"percent\": 71.08,\n                        \"correct\": 1357\n                      },\n                      \"pattern\": {\n                        \"total\": 3361,\n                        \"percent\": 73.61,\n                        \"correct\": 2474\n                      },\n                      \"symbol\": {\n                        \"total\": 429,\n                        \"percent\": 65.5,\n                        \"correct\": 281\n                      }\n                    },\n                    \"interval\": 60,\n                    \"length\": 73,\n                    \"scores\": {\n                      \"breakout\": 10,\n                      \"clarity\": 7,\n                      \"quality\": 8,\n                      \"initialtrend\": 10,\n                      \"uniformity\": 6\n                    },\n                    \"trendtype\": \"Continuation\",\n                    \"completed\": 1\n                  },\n                  \"data\": {\n                    \"points\": {\n                      \"support\": {\n                        \"y1\": 0.72456,\n                        \"y0\": 0.725455,\n                        \"x0\": 1520420400,\n                        \"x1\": 1520503200\n                      },\n                      \"resistance\": {\n                        \"y1\": 0.729755,\n                        \"y0\": 0.731095,\n                        \"x0\": 1520323200,\n                        \"x1\": 1520463600\n                      }\n                    },\n                    \"patternendtime\": 1520589600,\n                    \"prediction\": {\n                      \"timefrom\": 1520589600,\n                      \"pricelow\": 0.7316,\n                      \"timeto\": 1520773200,\n                      \"pricehigh\": 0.7349\n                    }\n                  },\n                  \"id\": 458552738,\n                  \"instrument\": \"NZD_USD\"\n                }\n              ],\n              \"provider\": \"autochartist\"\n          }\n    },\n}\n"
  },
  {
    "path": "oandapyV20/endpoints/responses/instruments.py",
    "content": "\"\"\"Responses.\n\nresponses serve both testing purpose aswell as dynamic docstring replacement\n\"\"\"\nresponses = {\n    \"_v3_instruments_instrument_orderbook\": {\n        \"url\": \"/v3/instruments/{instrument}/orderBook\",\n        \"instrument\": \"EUR_USD\",\n        \"params\": {},\n        \"response\": {\n             \"orderBook\": {\n                \"buckets\": [\n                  {\n                    \"price\": \"1.12850\",\n                    \"shortCountPercent\": \"0.2352\",\n                    \"longCountPercent\": \"0.2666\"\n                  },\n                  {\n                    \"price\": \"1.12900\",\n                    \"shortCountPercent\": \"0.2195\",\n                    \"longCountPercent\": \"0.3293\"\n                  },\n                  {\n                    \"price\": \"1.12950\",\n                    \"shortCountPercent\": \"0.3136\",\n                    \"longCountPercent\": \"0.2901\"\n                  },\n                  {\n                    \"price\": \"1.13000\",\n                    \"shortCountPercent\": \"0.3842\",\n                    \"longCountPercent\": \"0.4156\"\n                  },\n                  {\n                    \"price\": \"1.13050\",\n                    \"shortCountPercent\": \"0.1960\",\n                    \"longCountPercent\": \"0.3685\"\n                  },\n                  {\n                    \"price\": \"1.13100\",\n                    \"shortCountPercent\": \"0.2431\",\n                    \"longCountPercent\": \"0.2901\"\n                  },\n                  {\n                    \"price\": \"1.13150\",\n                    \"shortCountPercent\": \"0.2509\",\n                    \"longCountPercent\": \"0.3136\"\n                  },\n                  {\n                    \"price\": \"1.13200\",\n                    \"shortCountPercent\": \"0.2587\",\n                    \"longCountPercent\": \"0.3450\"\n                  },\n                  {\n                    \"price\": \"1.13250\",\n                    \"shortCountPercent\": \"0.3842\",\n                    \"longCountPercent\": \"0.2666\"\n                  },\n                  {\n                    \"price\": \"1.13300\",\n                    \"shortCountPercent\": \"0.3371\",\n                    \"longCountPercent\": \"0.3371\"\n                  },\n                  {\n                    \"price\": \"1.13350\",\n                    \"shortCountPercent\": \"0.3528\",\n                    \"longCountPercent\": \"0.2744\"\n                  },\n                  {\n                    \"price\": \"1.13400\",\n                    \"shortCountPercent\": \"0.3842\",\n                    \"longCountPercent\": \"0.3136\"\n                  },\n                  {\n                    \"price\": \"1.13450\",\n                    \"shortCountPercent\": \"0.2039\",\n                    \"longCountPercent\": \"0.2744\"\n                  },\n                  {\n                    \"price\": \"1.13500\",\n                    \"shortCountPercent\": \"0.1882\",\n                    \"longCountPercent\": \"0.3371\"\n                  },\n                  {\n                    \"price\": \"1.13550\",\n                    \"shortCountPercent\": \"0.0235\",\n                    \"longCountPercent\": \"0.0392\"\n                  },\n                  {\n                    \"price\": \"1.13600\",\n                    \"shortCountPercent\": \"0.0549\",\n                    \"longCountPercent\": \"0.0314\"\n                  },\n                  {\n                    \"price\": \"1.13650\",\n                    \"shortCountPercent\": \"0.1333\",\n                    \"longCountPercent\": \"0.0314\"\n                  },\n                  {\n                    \"price\": \"1.13700\",\n                    \"shortCountPercent\": \"0.1176\",\n                    \"longCountPercent\": \"0.1019\"\n                  },\n                  {\n                    \"price\": \"1.13750\",\n                    \"shortCountPercent\": \"0.1568\",\n                    \"longCountPercent\": \"0.0784\"\n                  },\n                  {\n                    \"price\": \"1.13800\",\n                    \"shortCountPercent\": \"0.1176\",\n                    \"longCountPercent\": \"0.0862\"\n                  },\n                  {\n                    \"price\": \"1.13850\",\n                    \"shortCountPercent\": \"0.2117\",\n                    \"longCountPercent\": \"0.1960\"\n                  },\n                  {\n                    \"price\": \"1.13900\",\n                    \"shortCountPercent\": \"0.4548\",\n                    \"longCountPercent\": \"0.2587\"\n                  },\n                  {\n                    \"price\": \"1.13950\",\n                    \"shortCountPercent\": \"0.2979\",\n                    \"longCountPercent\": \"0.3215\"\n                  },\n                  {\n                    \"price\": \"1.14000\",\n                    \"shortCountPercent\": \"0.7449\",\n                    \"longCountPercent\": \"0.2901\"\n                  },\n                  {\n                    \"price\": \"1.14050\",\n                    \"shortCountPercent\": \"0.2117\",\n                    \"longCountPercent\": \"0.1176\"\n                  },\n                  {\n                    \"price\": \"1.14100\",\n                    \"shortCountPercent\": \"0.1960\",\n                    \"longCountPercent\": \"0.1333\"\n                  },\n                  {\n                    \"price\": \"1.14150\",\n                    \"shortCountPercent\": \"0.1882\",\n                    \"longCountPercent\": \"0.1176\"\n                  },\n                ],\n                \"instrument\": \"EUR_USD\",\n                \"price\": \"1.13609\",\n                \"bucketWidth\": \"0.00050\",\n                \"time\": \"2017-06-28T10:00:00Z\"\n              }\n        }\n    },\n    \"_v3_instruments_instrument_positionbook\": {\n        \"url\": \"/v3/instruments/{instrument}/positionBook\",\n        \"instrument\": \"EUR_USD\",\n        \"params\": {},\n        \"response\": {\n              \"positionBook\": {\n                \"buckets\": [\n                  {\n                    \"price\": \"1.12800\",\n                    \"shortCountPercent\": \"0.2670\",\n                    \"longCountPercent\": \"0.2627\"\n                  },\n                  {\n                    \"price\": \"1.12850\",\n                    \"shortCountPercent\": \"0.2034\",\n                    \"longCountPercent\": \"0.2712\"\n                  },\n                  {\n                    \"price\": \"1.12900\",\n                    \"shortCountPercent\": \"0.2034\",\n                    \"longCountPercent\": \"0.2161\"\n                  },\n                  {\n                    \"price\": \"1.12950\",\n                    \"shortCountPercent\": \"0.2670\",\n                    \"longCountPercent\": \"0.2839\"\n                  },\n                  {\n                    \"price\": \"1.13000\",\n                    \"shortCountPercent\": \"0.2755\",\n                    \"longCountPercent\": \"0.3221\"\n                  },\n                  {\n                    \"price\": \"1.13050\",\n                    \"shortCountPercent\": \"0.1949\",\n                    \"longCountPercent\": \"0.2839\"\n                  },\n                  {\n                    \"price\": \"1.13100\",\n                    \"shortCountPercent\": \"0.2288\",\n                    \"longCountPercent\": \"0.2712\"\n                  },\n                  {\n                    \"price\": \"1.13150\",\n                    \"shortCountPercent\": \"0.2416\",\n                    \"longCountPercent\": \"0.2712\"\n                  },\n                  {\n                    \"price\": \"1.13200\",\n                    \"shortCountPercent\": \"0.2204\",\n                    \"longCountPercent\": \"0.3178\"\n                  },\n                  {\n                    \"price\": \"1.13250\",\n                    \"shortCountPercent\": \"0.2543\",\n                    \"longCountPercent\": \"0.2458\"\n                  },\n                  {\n                    \"price\": \"1.13300\",\n                    \"shortCountPercent\": \"0.2839\",\n                    \"longCountPercent\": \"0.2585\"\n                  },\n                  {\n                    \"price\": \"1.13350\",\n                    \"shortCountPercent\": \"0.3602\",\n                    \"longCountPercent\": \"0.3094\"\n                  },\n                  {\n                    \"price\": \"1.13400\",\n                    \"shortCountPercent\": \"0.2882\",\n                    \"longCountPercent\": \"0.3560\"\n                  },\n                  {\n                    \"price\": \"1.13450\",\n                    \"shortCountPercent\": \"0.2500\",\n                    \"longCountPercent\": \"0.3009\"\n                  },\n                  {\n                    \"price\": \"1.13500\",\n                    \"shortCountPercent\": \"0.1738\",\n                    \"longCountPercent\": \"0.3475\"\n                  },\n                  {\n                    \"price\": \"1.13550\",\n                    \"shortCountPercent\": \"0.2119\",\n                    \"longCountPercent\": \"0.2797\"\n                  },\n                  {\n                    \"price\": \"1.13600\",\n                    \"shortCountPercent\": \"0.1483\",\n                    \"longCountPercent\": \"0.3094\"\n                  },\n                  {\n                    \"price\": \"1.13650\",\n                    \"shortCountPercent\": \"0.1483\",\n                    \"longCountPercent\": \"0.1314\"\n                  },\n                  {\n                    \"price\": \"1.13700\",\n                    \"shortCountPercent\": \"0.1568\",\n                    \"longCountPercent\": \"0.2034\"\n                  },\n                  {\n                    \"price\": \"1.13750\",\n                    \"shortCountPercent\": \"0.1398\",\n                    \"longCountPercent\": \"0.1271\"\n                  },\n                  {\n                    \"price\": \"1.13800\",\n                    \"shortCountPercent\": \"0.1314\",\n                    \"longCountPercent\": \"0.2034\"\n                  },\n                  {\n                    \"price\": \"1.13850\",\n                    \"shortCountPercent\": \"0.1483\",\n                    \"longCountPercent\": \"0.1695\"\n                  },\n                  {\n                    \"price\": \"1.13900\",\n                    \"shortCountPercent\": \"0.2924\",\n                    \"longCountPercent\": \"0.1653\"\n                  },\n                  {\n                    \"price\": \"1.13950\",\n                    \"shortCountPercent\": \"0.1526\",\n                    \"longCountPercent\": \"0.1865\"\n                  },\n                  {\n                    \"price\": \"1.14000\",\n                    \"shortCountPercent\": \"0.4365\",\n                    \"longCountPercent\": \"0.2034\"\n                  },\n                  {\n                    \"price\": \"1.14050\",\n                    \"shortCountPercent\": \"0.1398\",\n                    \"longCountPercent\": \"0.1144\"\n                  }\n                ],\n                \"instrument\": \"EUR_USD\",\n                \"price\": \"1.13609\",\n                \"bucketWidth\": \"0.00050\",\n                \"time\": \"2017-06-28T10:00:00Z\"\n              }\n        }\n    },\n    \"_v3_instruments_instrument_candles\": {\n        \"url\": \"/v3/instruments/{instrument}/candles\",\n        \"instrument\": \"DE30_EUR\",\n        \"params\": {\n            \"count\": 5,\n            \"granularity\": \"M5\"\n        },\n        \"response\": {\n            \"candles\": [\n                {\n                  \"volume\": 132,\n                  \"time\": \"2016-10-17T19:35:00.000000000Z\",\n                  \"complete\": True,\n                  \"mid\": {\n                    \"h\": \"10508.0\",\n                    \"c\": \"10506.0\",\n                    \"l\": \"10503.8\",\n                    \"o\": \"10503.8\"\n                  }\n                },\n                {\n                  \"volume\": 162,\n                  \"time\": \"2016-10-17T19:40:00.000000000Z\",\n                  \"complete\": True,\n                  \"mid\": {\n                    \"h\": \"10507.0\",\n                    \"c\": \"10504.9\",\n                    \"l\": \"10502.0\",\n                    \"o\": \"10506.0\"\n                  }\n                },\n                {\n                  \"volume\": 196,\n                  \"time\": \"2016-10-17T19:45:00.000000000Z\",\n                  \"complete\": True,\n                  \"mid\": {\n                    \"h\": \"10509.8\",\n                    \"c\": \"10505.0\",\n                    \"l\": \"10502.6\",\n                    \"o\": \"10504.9\"\n                  }\n                },\n                {\n                  \"volume\": 153,\n                  \"time\": \"2016-10-17T19:50:00.000000000Z\",\n                  \"complete\": True,\n                  \"mid\": {\n                    \"h\": \"10510.1\",\n                    \"c\": \"10509.0\",\n                    \"l\": \"10504.2\",\n                    \"o\": \"10505.0\"\n                  }\n                },\n                {\n                  \"volume\": 172,\n                  \"time\": \"2016-10-17T19:55:00.000000000Z\",\n                  \"complete\": True,\n                  \"mid\": {\n                    \"h\": \"10509.8\",\n                    \"c\": \"10507.8\",\n                    \"l\": \"10503.2\",\n                    \"o\": \"10509.0\"\n                  }\n                }\n            ],\n            \"instrument\": \"DE30/EUR\",\n            \"granularity\": \"M5\"\n        }\n    }\n}\n"
  },
  {
    "path": "oandapyV20/endpoints/responses/orders.py",
    "content": "# -*- coding: utf-8 -*-\n\"\"\"Responses.\n\nresponses serve both testing purpose aswell as dynamic docstring replacement\n\"\"\"\nresponses = {\n    \"_v3_accounts_accountID_orders_create\": {\n        \"url\": \"v3/accounts/{accountID}/orders\",\n        \"body\": {\n                \"order\": {\n                    \"stopLossOnFill\": {\n                        \"timeInForce\": \"GTC\",\n                        \"price\": \"1.22\"\n                    },\n                    \"units\": \"-100\",\n                    \"price\": \"1.2\",\n                    \"instrument\": \"EUR_USD\",\n                    \"timeInForce\": \"GTC\",\n                    \"type\": \"LIMIT\",\n                    \"positionFill\": \"DEFAULT\"\n                }\n        },\n        \"response\": {\n            \"orderCreateTransaction\": {\n                \"timeInForce\": \"GTC\",\n                \"triggerCondition\": \"TRIGGER_DEFAULT\",\n                \"positionFill\": \"DEFAULT\",\n                \"stopLossOnFill\": {\n                    \"timeInForce\": \"GTC\",\n                    \"price\": \"1.22000\"\n                },\n                \"userID\": 1435156,\n                \"id\": \"2304\",\n                \"batchID\": \"2304\",\n                \"instrument\": \"EUR_USD\",\n                \"reason\": \"CLIENT_ORDER\",\n                \"time\": \"2016-10-24T21:48:18.593753865Z\",\n                \"units\": \"-100\",\n                \"type\": \"LIMIT_ORDER\",\n                \"price\": \"1.20000\",\n                \"accountID\": \"101-004-1435156-001\"\n            },\n            \"relatedTransactionIDs\": [\n                \"2304\"\n            ],\n            \"lastTransactionID\": \"2304\"\n        }\n    },\n    \"_v3_accounts_accountID_orders_pending\": {\n        \"url\": \"v3/accounts/{accountID}/orders\",\n        \"response\": {\n            \"orders\": [\n                {\n                    \"timeInForce\": \"GTC\",\n                    \"triggerCondition\": \"TRIGGER_DEFAULT\",\n                    \"partialFill\": \"DEFAULT_FILL\",\n                    \"positionFill\": \"POSITION_DEFAULT\",\n                    \"stopLossOnFill\": {\n                        \"timeInForce\": \"GTC\",\n                        \"price\": \"1.22000\"\n                    },\n                    \"id\": \"2304\",\n                    \"price\": \"1.20000\",\n                    \"instrument\": \"EUR_USD\",\n                    \"state\": \"PENDING\",\n                    \"units\": \"-100\",\n                    \"clientExtensions\": {\n                        \"comment\": \"myComment\",\n                        \"id\": \"myID\"\n                    },\n                    \"type\": \"LIMIT\",\n                    \"createTime\": \"2016-10-24T21:48:18.593753865Z\"\n                }\n            ],\n            \"lastTransactionID\": \"2305\"\n        }\n    },\n    \"_v3_accounts_accountID_order_cancel\": {\n        \"url\": \"v3/accounts/{accountID}/orders/{orderID}/cancel\",\n        \"orderID\": \"2307\",\n        \"response\": {\n            \"orderCancelTransaction\": {\n                \"orderID\": \"2307\",\n                \"clientOrderID\": \"myID\",\n                \"userID\": 1435156,\n                \"batchID\": \"2308\",\n                \"reason\": \"CLIENT_REQUEST\",\n                \"time\": \"2016-10-25T20:53:03.789670387Z\",\n                \"type\": \"ORDER_CANCEL\",\n                \"id\": \"2308\",\n                \"accountID\": \"101-004-1435156-001\"\n            },\n            \"relatedTransactionIDs\": [\n                \"2308\"\n            ],\n            \"lastTransactionID\": \"2308\"\n        }\n    },\n    \"_v3_accounts_accountID_orders_list\": {\n        \"url\": \"v3/accounts/{accountID}/orders\",\n        \"response\": {\n            \"orders\": [\n                {\n                    \"triggerCondition\": \"TRIGGER_DEFAULT\",\n                    \"partialFill\": \"DEFAULT_FILL\",\n                    \"price\": \"1.20000\",\n                    \"stopLossOnFill\": {\n                        \"timeInForce\": \"GTC\",\n                        \"price\": \"1.22000\"\n                    },\n                    \"createTime\": \"2016-10-05T10:25:47.627003645Z\",\n                    \"timeInForce\": \"GTC\",\n                    \"instrument\": \"EUR_USD\",\n                    \"state\": \"PENDING\",\n                    \"units\": \"-100\",\n                    \"id\": \"2125\",\n                    \"type\": \"LIMIT\",\n                    \"positionFill\": \"POSITION_DEFAULT\"\n                }\n            ],\n            \"lastTransactionID\": \"2129\"\n        }\n    },\n    \"_v3_accounts_accountID_order_details\": {\n        \"url\": \"v3/accounts/{accountID}/orders/{orderID}/details\",\n        \"orderID\": \"2309\",\n        \"response\": {\n            \"order\": {\n                \"triggerCondition\": \"TRIGGER_DEFAULT\",\n                \"partialFill\": \"DEFAULT_FILL\",\n                \"price\": \"1.20000\",\n                \"stopLossOnFill\": {\n                    \"timeInForce\": \"GTC\",\n                    \"price\": \"1.22000\"\n                },\n                \"createTime\": \"2016-10-25T21:07:21.065554321Z\",\n                \"timeInForce\": \"GTC\",\n                \"instrument\": \"EUR_USD\",\n                \"state\": \"PENDING\",\n                \"units\": \"-100\",\n                \"id\": \"2309\",\n                \"type\": \"LIMIT\",\n                \"positionFill\": \"POSITION_DEFAULT\"\n            },\n            \"lastTransactionID\": \"2309\"\n        }\n    },\n    \"_v3_accounts_accountID_order_replace\": {\n        \"url\": \"v3/accounts/{accountID}/orders\",\n        \"body\": {\n            \"order\": {\n                \"units\": \"-500000\",\n                \"type\": \"LIMIT\",\n                \"instrument\": \"EUR_USD\",\n                \"price\": \"1.25000\",\n            }\n        },\n        \"response\": {\n                \"orderCreateTransaction\": {\n                    \"timeInForce\": \"GTC\",\n                    \"triggerCondition\": \"TRIGGER_DEFAULT\",\n                    \"replacesOrderID\": \"2304\",\n                    \"positionFill\": \"DEFAULT\",\n                    \"userID\": 1435156,\n                    \"units\": \"-500000\",\n                    \"batchID\": \"2306\",\n                    \"instrument\": \"EUR_USD\",\n                    \"reason\": \"REPLACEMENT\",\n                    \"time\": \"2016-10-25T19:45:38.558056359Z\",\n                    \"price\": \"1.25000\",\n                    \"clientExtensions\": {\n                        \"comment\": \"myComment\",\n                        \"id\": \"myID\"\n                    },\n                    \"type\": \"LIMIT_ORDER\",\n                    \"id\": \"2307\",\n                    \"accountID\": \"101-004-1435156-001\"\n                },\n                \"orderCancelTransaction\": {\n                    \"orderID\": \"2304\",\n                    \"clientOrderID\": \"myID\",\n                    \"replacedByOrderID\": \"2307\",\n                    \"userID\": 1435156,\n                    \"batchID\": \"2306\",\n                    \"reason\": \"CLIENT_REQUEST_REPLACED\",\n                    \"time\": \"2016-10-25T19:45:38.558056359Z\",\n                    \"type\": \"ORDER_CANCEL\",\n                    \"id\": \"2306\",\n                    \"accountID\": \"101-004-1435156-001\"\n                },\n                \"relatedTransactionIDs\": [\n                    \"2306\",\n                    \"2307\"\n                ],\n                \"lastTransactionID\": \"2307\"\n        }\n    },\n    \"_v3_accounts_accountID_order_clientextensions\": {\n        \"url\": \"v3/accounts/{accountID}/orders/{orderID}/clientExtensions\",\n        \"orderID\": 2304,\n        \"body\": {\n            \"clientExtensions\": {\n                \"id\": \"myID\",\n                \"comment\": \"myComment\",\n            }\n        },\n        \"response\": {\n            \"relatedTransactionIDs\": [\n                \"2305\"\n            ],\n            \"orderClientExtensionsModifyTransaction\": {\n                \"orderID\": \"2304\",\n                \"userID\": 1435156,\n                \"batchID\": \"2305\",\n                \"clientExtensionsModify\": {\n                    \"comment\": \"myComment\",\n                    \"id\": \"myID\"\n                },\n                \"time\": \"2016-10-25T15:56:43.075594239Z\",\n                \"type\": \"ORDER_CLIENT_EXTENSIONS_MODIFY\",\n                \"id\": \"2305\",\n                \"accountID\": \"101-004-1435156-001\"\n            },\n            \"lastTransactionID\": \"2305\"\n        }\n    }\n}\n"
  },
  {
    "path": "oandapyV20/endpoints/responses/positions.py",
    "content": "\"\"\"Responses.\n\nresponses serve both testing purpose aswell as dynamic docstring replacement\n\"\"\"\nresponses = {\n    \"_v3_accounts_accountID_positions\": {\n        \"url\": \"v3/accounts/{accountID}/positions\",\n        \"response\": {\n            \"positions\": [\n                {\n                    \"short\": {\n                        \"units\": \"0\",\n                        \"resettablePL\": \"-272.6805\",\n                        \"unrealizedPL\": \"0.0000\",\n                        \"pl\": \"-272.6805\"\n                    },\n                    \"unrealizedPL\": \"0.0000\",\n                    \"long\": {\n                        \"units\": \"0\",\n                        \"resettablePL\": \"0.0000\",\n                        \"unrealizedPL\": \"0.0000\",\n                        \"pl\": \"0.0000\"\n                    },\n                    \"instrument\": \"EUR_GBP\",\n                    \"resettablePL\": \"-272.6805\",\n                    \"pl\": \"-272.6805\"\n                },\n                {\n                    \"short\": {\n                        \"unrealizedPL\": \"870.0000\",\n                        \"units\": \"-20\",\n                        \"resettablePL\": \"-13959.3000\",\n                        \"tradeIDs\": [\n                            \"2121\",\n                            \"2123\"\n                        ],\n                        \"averagePrice\": \"10581.5\",\n                        \"pl\": \"-13959.3000\"\n                    },\n                    \"unrealizedPL\": \"870.0000\",\n                    \"long\": {\n                        \"units\": \"0\",\n                        \"resettablePL\": \"404.5000\",\n                        \"unrealizedPL\": \"0.0000\",\n                        \"pl\": \"404.5000\"\n                    },\n                    \"instrument\": \"DE30_EUR\",\n                    \"resettablePL\": \"-13554.8000\",\n                    \"pl\": \"-13554.8000\"\n                },\n                {\n                    \"short\": {\n                        \"units\": \"0\",\n                        \"resettablePL\": \"0.0000\",\n                        \"unrealizedPL\": \"0.0000\",\n                        \"pl\": \"0.0000\"\n                    },\n                    \"unrealizedPL\": \"0.0000\",\n                    \"long\": {\n                        \"units\": \"0\",\n                        \"resettablePL\": \"-12.8720\",\n                        \"unrealizedPL\": \"0.0000\",\n                        \"pl\": \"-12.8720\"\n                    },\n                    \"instrument\": \"EUR_USD\",\n                    \"resettablePL\": \"-12.8720\",\n                    \"pl\": \"-12.8720\"\n                }\n            ],\n            \"lastTransactionID\": \"2124\"\n        }\n    },\n    \"_v3_accounts_accountID_openpositions\": {\n        \"url\": \"v3/accounts/{accountID}/positions\",\n        \"response\": {\n            \"positions\": [\n                {\n                    \"short\": {\n                        \"units\": \"0\",\n                        \"resettablePL\": \"-14164.3000\",\n                        \"unrealizedPL\": \"0.0000\",\n                        \"pl\": \"-14164.3000\"\n                    },\n                    \"unrealizedPL\": \"-284.0000\",\n                    \"long\": {\n                        \"unrealizedPL\": \"-284.0000\",\n                        \"units\": \"10\",\n                        \"resettablePL\": \"404.5000\",\n                        \"tradeIDs\": [\n                            \"2315\"\n                        ],\n                        \"averagePrice\": \"10678.3\",\n                        \"pl\": \"404.5000\"\n                    },\n                    \"instrument\": \"DE30_EUR\",\n                    \"resettablePL\": \"-13759.8000\",\n                    \"pl\": \"-13759.8000\"\n                },\n                {\n                    \"short\": {\n                        \"unrealizedPL\": \"-0.0738\",\n                        \"units\": \"-100\",\n                        \"resettablePL\": \"0.0000\",\n                        \"tradeIDs\": [\n                            \"2323\"\n                        ],\n                        \"averagePrice\": \"1.09843\",\n                        \"pl\": \"0.0000\"\n                    },\n                    \"unrealizedPL\": \"-0.0738\",\n                    \"long\": {\n                        \"units\": \"0\",\n                        \"resettablePL\": \"-44.6272\",\n                        \"unrealizedPL\": \"0.0000\",\n                        \"pl\": \"-44.6272\"\n                    },\n                    \"instrument\": \"EUR_USD\",\n                    \"resettablePL\": \"-44.6272\",\n                    \"pl\": \"-44.6272\"\n                }\n            ],\n            \"lastTransactionID\": \"2327\"\n        }\n    },\n    \"_v3_accounts_accountID_positiondetails\": {\n        \"url\": \"v3/accounts/{accountID}/positions/{instrument}\",\n        \"response\": {\n            \"position\": {\n                \"short\": {\n                    \"unrealizedPL\": \"-0.0738\",\n                    \"units\": \"-100\",\n                    \"resettablePL\": \"0.0000\",\n                    \"tradeIDs\": [\n                        \"2323\"\n                    ],\n                    \"averagePrice\": \"1.09843\",\n                    \"pl\": \"0.0000\"\n                },\n                \"unrealizedPL\": \"-0.0738\",\n                \"long\": {\n                    \"units\": \"0\",\n                    \"resettablePL\": \"-44.6272\",\n                    \"unrealizedPL\": \"0.0000\",\n                    \"pl\": \"-44.6272\"\n                },\n                \"instrument\": \"EUR_USD\",\n                \"resettablePL\": \"-44.6272\",\n                \"pl\": \"-44.6272\"\n            },\n            \"lastTransactionID\": \"2327\"\n        }\n    },\n    \"_v3_accounts_accountID_position_close\": {\n        \"url\": \"v3/accounts/{accountID}/positions/{instrument}/close\",\n        \"body\": {\n            \"longUnits\": \"ALL\"\n        },\n        \"response\": {\n            \"lastTransactionID\": \"6391\",\n            \"longOrderCreateTransaction\": {\n                \"accountID\": \"<ACCOUNT>\",\n                \"batchID\": \"6390\",\n                \"id\": \"6390\",\n                \"instrument\": \"EUR_USD\",\n                \"longPositionCloseout\": {\n                    \"instrument\": \"EUR_USD\",\n                    \"units\": \"ALL\"\n                },\n                \"positionFill\": \"REDUCE_ONLY\",\n                \"reason\": \"POSITION_CLOSEOUT\",\n                \"time\": \"2016-06-22T18:41:35.034041665Z\",\n                \"timeInForce\": \"FOK\",\n                \"type\": \"MARKET_ORDER\",\n                \"units\": \"-251\",\n                \"userID\": \"<USERID>\"\n            },\n            \"longOrderFillTransaction\": {\n                \"accountBalance\": \"43650.69807\",\n                \"accountID\": \"<ACCOUNT>\",\n                \"batchID\": \"6390\",\n                \"financing\": \"0.00000\",\n                \"id\": \"6391\",\n                \"instrument\": \"EUR_USD\",\n                \"orderID\": \"6390\",\n                \"pl\": \"-0.03370\",\n                \"price\": \"1.13018\",\n                \"reason\": \"MARKET_ORDER_POSITION_CLOSEOUT\",\n                \"time\": \"2016-06-22T18:41:35.034041665Z\",\n                \"tradesClosed\": [\n                    {\n                        \"financing\": \"0.00000\",\n                        \"realizedPL\": \"-0.00013\",\n                        \"tradeID\": \"6383\",\n                        \"units\": \"-1\"\n                    },\n                    {\n                        \"financing\": \"0.00000\",\n                        \"realizedPL\": \"-0.03357\",\n                        \"tradeID\": \"6385\",\n                        \"units\": \"-250\"\n                    }\n                ],\n                \"type\": \"ORDER_FILL\",\n                \"units\": \"-251\",\n                \"userID\": \"<USERID>\"\n            },\n            \"relatedTransactionIDs\": [\n                \"6390\",\n                \"6391\"\n            ]\n        }\n    }\n}\n"
  },
  {
    "path": "oandapyV20/endpoints/responses/pricing.py",
    "content": "\"\"\"Responses.\n\nresponses serve both testing purpose aswell as dynamic docstring replacement\n\"\"\"\nresponses = {\n    \"_v3_accounts_accountID_pricing\": {\n        \"url\": \"v3/accounts/{accountID}/pricing\",\n        \"params\": {\n            \"instruments\": \"EUR_USD,EUR_JPY\"\n        },\n        \"response\": {\n            \"prices\": [\n                {\n                    \"status\": \"tradeable\",\n                    \"quoteHomeConversionFactors\": {\n                        \"negativeUnits\": \"0.89160730\",\n                        \"positiveUnits\": \"0.89150397\"\n                    },\n                    \"asks\": [\n                        {\n                            \"price\": \"1.12170\",\n                            \"liquidity\": 10000000\n                        },\n                        {\n                            \"price\": \"1.12172\",\n                            \"liquidity\": 10000000\n                        }\n                    ],\n                    \"unitsAvailable\": {\n                        \"default\": {\n                            \"short\": \"506246\",\n                            \"long\": \"506128\"\n                        },\n                        \"reduceOnly\": {\n                            \"short\": \"0\",\n                            \"long\": \"0\"\n                        },\n                        \"openOnly\": {\n                            \"short\": \"506246\",\n                            \"long\": \"506128\"\n                        },\n                        \"reduceFirst\": {\n                            \"short\": \"506246\",\n                            \"long\": \"506128\"\n                        }\n                    },\n                    \"closeoutBid\": \"1.12153\",\n                    \"bids\": [\n                        {\n                            \"price\": \"1.12157\",\n                            \"liquidity\": 10000000\n                        },\n                        {\n                            \"price\": \"1.12155\",\n                            \"liquidity\": 10000000\n                        }\n                    ],\n                    \"instrument\": \"EUR_USD\",\n                    \"time\": \"2016-10-05T05:28:16.729643492Z\",\n                    \"closeoutAsk\": \"1.12174\"\n                },\n                {\n                    \"status\": \"tradeable\",\n                    \"quoteHomeConversionFactors\": {\n                        \"negativeUnits\": \"0.00867085\",\n                        \"positiveUnits\": \"0.00866957\"\n                    },\n                    \"asks\": [\n                        {\n                            \"price\": \"115.346\",\n                            \"liquidity\": 1000000\n                        },\n                        {\n                            \"price\": \"115.347\",\n                            \"liquidity\": 2000000\n                        },\n                        {\n                            \"price\": \"115.348\",\n                            \"liquidity\": 5000000\n                        },\n                        {\n                            \"price\": \"115.350\",\n                            \"liquidity\": 10000000\n                        }\n                    ],\n                    \"unitsAvailable\": {\n                        \"default\": {\n                            \"short\": \"506262\",\n                            \"long\": \"506112\"\n                        },\n                        \"reduceOnly\": {\n                            \"short\": \"0\",\n                            \"long\": \"0\"\n                        },\n                        \"openOnly\": {\n                            \"short\": \"506262\",\n                            \"long\": \"506112\"\n                        },\n                        \"reduceFirst\": {\n                            \"short\": \"506262\",\n                            \"long\": \"506112\"\n                        }\n                    },\n                    \"closeoutBid\": \"115.325\",\n                    \"bids\": [\n                        {\n                            \"price\": \"115.329\",\n                            \"liquidity\": 1000000\n                        },\n                        {\n                            \"price\": \"115.328\",\n                            \"liquidity\": 2000000\n                        },\n                        {\n                            \"price\": \"115.327\",\n                            \"liquidity\": 5000000\n                        },\n                        {\n                            \"price\": \"115.325\",\n                            \"liquidity\": 10000000\n                        }\n                    ],\n                    \"instrument\": \"EUR_JPY\",\n                    \"time\": \"2016-10-05T05:28:15.621238671Z\",\n                    \"closeoutAsk\": \"115.350\"\n                }\n            ]\n        }\n    },\n    \"_v3_accounts_accountID_pricing_stream\": {\n        \"url\": \"v3/accounts/{accountID}/pricing/stream\",\n        \"params\": {\n            \"instruments\": \"EUR_USD,EUR_JPY\"\n        },\n        \"response\": [\n             {\n                \"status\": \"tradeable\",\n                \"asks\": [\n                    {\n                        \"price\": \"114.312\",\n                        \"liquidity\": 1000000\n                    },\n                    {\n                        \"price\": \"114.313\",\n                        \"liquidity\": 2000000\n                    },\n                    {\n                        \"price\": \"114.314\",\n                        \"liquidity\": 5000000\n                    },\n                    {\n                        \"price\": \"114.316\",\n                        \"liquidity\": 10000000\n                    }\n                ],\n                \"closeoutBid\": \"114.291\",\n                \"bids\": [\n                    {\n                        \"price\": \"114.295\",\n                        \"liquidity\": 1000000\n                    },\n                    {\n                        \"price\": \"114.294\",\n                        \"liquidity\": 2000000\n                    },\n                    {\n                        \"price\": \"114.293\",\n                        \"liquidity\": 5000000\n                    },\n                    {\n                        \"price\": \"114.291\",\n                        \"liquidity\": 10000000\n                    }\n                ],\n                \"instrument\": \"EUR_JPY\",\n                \"time\": \"2016-10-27T08:38:43.094548890Z\",\n                \"closeoutAsk\": \"114.316\",\n                \"type\": \"PRICE\"\n             },\n             {\n                \"type\": \"HEARTBEAT\",\n                \"time\": \"2016-10-27T08:38:44.327443673Z\"\n             },\n             {\n                \"status\": \"tradeable\",\n                \"asks\": [\n                    {\n                        \"price\": \"1.09188\",\n                        \"liquidity\": 10000000\n                    },\n                    {\n                        \"price\": \"1.09190\",\n                        \"liquidity\": 10000000\n                    }\n                ],\n                \"closeoutBid\": \"1.09173\",\n                \"bids\": [\n                    {\n                        \"price\": \"1.09177\",\n                        \"liquidity\": 10000000\n                    },\n                    {\n                        \"price\": \"1.09175\",\n                        \"liquidity\": 10000000\n                    }\n                ],\n                \"instrument\": \"EUR_USD\",\n                \"time\": \"2016-10-27T08:38:45.664613867Z\",\n                \"closeoutAsk\": \"1.09192\",\n                \"type\": \"PRICE\"\n             },\n             {\n                \"status\": \"tradeable\",\n                \"asks\": [\n                    {\n                        \"price\": \"114.315\",\n                        \"liquidity\": 1000000\n                    },\n                    {\n                        \"price\": \"114.316\",\n                        \"liquidity\": 2000000\n                    },\n                    {\n                        \"price\": \"114.317\",\n                        \"liquidity\": 5000000\n                    },\n                    {\n                        \"price\": \"114.319\",\n                        \"liquidity\": 10000000\n                    }\n                ],\n                \"closeoutBid\": \"114.294\",\n                \"bids\": [\n                    {\n                        \"price\": \"114.298\",\n                        \"liquidity\": 1000000\n                    },\n                    {\n                        \"price\": \"114.297\",\n                        \"liquidity\": 2000000\n                    },\n                    {\n                        \"price\": \"114.296\",\n                        \"liquidity\": 5000000\n                    },\n                    {\n                        \"price\": \"114.294\",\n                        \"liquidity\": 10000000\n                    }\n                ],\n                \"instrument\": \"EUR_JPY\",\n                \"time\": \"2016-10-27T08:38:45.681572782Z\",\n                \"closeoutAsk\": \"114.319\",\n                \"type\": \"PRICE\"\n             }\n        ]\n    }\n}\n"
  },
  {
    "path": "oandapyV20/endpoints/responses/trades.py",
    "content": "\"\"\"Responses.\n\nresponses serve both testing purpose aswell as dynamic docstring replacement\n\"\"\"\nresponses = {\n    \"_v3_accounts_accountID_trades\": {\n        \"url\": \"v3/accounts/{accountID}/trades\",\n        \"params\": {\n            \"instrument\": \"DE30_EUR,EUR_USD\"\n        },\n        \"response\": {\n            \"trades\": [\n                {\n                    \"financing\": \"0.0000\",\n                    \"openTime\": \"2016-10-28T14:28:05.231759081Z\",\n                    \"price\": \"10678.3\",\n                    \"unrealizedPL\": \"25.0000\",\n                    \"realizedPL\": \"0.0000\",\n                    \"instrument\": \"DE30_EUR\",\n                    \"state\": \"OPEN\",\n                    \"initialUnits\": \"10\",\n                    \"currentUnits\": \"10\",\n                    \"id\": \"2315\"\n                },\n                {\n                    \"financing\": \"0.0000\",\n                    \"openTime\": \"2016-10-28T14:27:19.011002322Z\",\n                    \"price\": \"1.09448\",\n                    \"unrealizedPL\": \"-0.0933\",\n                    \"realizedPL\": \"0.0000\",\n                    \"instrument\": \"EUR_USD\",\n                    \"state\": \"OPEN\",\n                    \"initialUnits\": \"100\",\n                    \"currentUnits\": \"100\",\n                    \"id\": \"2313\"\n                }\n            ],\n            \"lastTransactionID\": \"2315\"\n        }\n    },\n    \"_v3_accounts_accountID_opentrades\": {\n        \"url\": \"v3/accounts/{accountID}/openTrades\",\n        \"response\": {\n            \"trades\": [\n                {\n                    \"financing\": \"0.0000\",\n                    \"openTime\": \"2016-10-28T14:28:05.231759081Z\",\n                    \"price\": \"10678.3\",\n                    \"unrealizedPL\": \"136.0000\",\n                    \"realizedPL\": \"0.0000\",\n                    \"instrument\": \"DE30_EUR\",\n                    \"state\": \"OPEN\",\n                    \"initialUnits\": \"10\",\n                    \"currentUnits\": \"10\",\n                    \"id\": \"2315\"\n                }\n            ],\n            \"lastTransactionID\": \"2317\"\n        }\n    },\n    \"_v3_account_accountID_trades_details\": {\n        # tradeID 2315\n        \"url\": \"v3/accounts/{accountID}/trades/{tradeID}\",\n        \"response\": {\n            \"lastTransactionID\": \"2317\",\n            \"trade\": {\n                \"financing\": \"0.0000\",\n                \"openTime\": \"2016-10-28T14:28:05.231759081Z\",\n                \"price\": \"10678.3\",\n                \"unrealizedPL\": \"226.0000\",\n                \"realizedPL\": \"0.0000\",\n                \"instrument\": \"DE30_EUR\",\n                \"state\": \"OPEN\",\n                \"initialUnits\": \"10\",\n                \"currentUnits\": \"10\",\n                \"id\": \"2315\"\n            }\n        }\n    },\n    \"_v3_account_accountID_trades_close\": {\n        \"url\": \"v3/accounts/{accountID}/trades/{tradeID}/close\",\n        \"body\": {\n            \"units\": 100\n        },\n        \"response\": {\n            \"orderFillTransaction\": {\n                \"orderID\": \"2316\",\n                \"financing\": \"0.0000\",\n                \"instrument\": \"EUR_USD\",\n                \"price\": \"1.09289\",\n                \"userID\": 1435156,\n                \"batchID\": \"2316\",\n                \"accountBalance\": \"33848.1208\",\n                \"reason\": \"MARKET_ORDER_TRADE_CLOSE\",\n                \"tradesClosed\": [\n                    {\n                        \"units\": \"-100\",\n                        \"financing\": \"0.0000\",\n                        \"realizedPL\": \"-0.1455\",\n                        \"tradeID\": \"2313\"\n                    }\n                ],\n                \"time\": \"2016-10-28T15:11:58.023004583Z\",\n                \"units\": \"-100\",\n                \"type\": \"ORDER_FILL\",\n                \"id\": \"2317\",\n                \"pl\": \"-0.1455\",\n                \"accountID\": \"101-004-1435156-001\"\n            },\n            \"orderCreateTransaction\": {\n                \"timeInForce\": \"FOK\",\n                \"positionFill\": \"REDUCE_ONLY\",\n                \"userID\": 1435156,\n                \"batchID\": \"2316\",\n                \"instrument\": \"EUR_USD\",\n                \"reason\": \"TRADE_CLOSE\",\n                \"tradeClose\": {\n                    \"units\": \"100\",\n                    \"tradeID\": \"2313\"\n                },\n                \"time\": \"2016-10-28T15:11:58.023004583Z\",\n                \"units\": \"-100\",\n                \"type\": \"MARKET_ORDER\",\n                \"id\": \"2316\",\n                \"accountID\": \"101-004-1435156-001\"\n            },\n            \"relatedTransactionIDs\": [\n                \"2316\",\n                \"2317\"\n            ],\n            \"lastTransactionID\": \"2317\"\n        }\n    },\n    \"_v3_account_accountID_trades_cltext\": {\n        \"url\": \"v3/accounts/{accountID}/trades/{tradeID}/close\",\n        \"body\": {\n            \"clientExtensions\": {\n                \"comment\": \"myComment\",\n                \"id\": \"myID2315\",\n            }\n        },\n        \"response\": {\n            \"tradeClientExtensionsModifyTransaction\": {\n                \"tradeID\": \"2315\",\n                \"userID\": 1435156,\n                \"batchID\": \"2319\",\n                \"time\": \"2016-10-28T20:32:39.356516787Z\",\n                \"tradeClientExtensionsModify\": {\n                    \"comment\": \"myComment\",\n                    \"id\": \"myID2315\"\n                },\n                \"type\": \"TRADE_CLIENT_EXTENSIONS_MODIFY\",\n                \"id\": \"2319\",\n                \"accountID\": \"101-004-1435156-001\"\n            },\n            \"relatedTransactionIDs\": [\n                \"2319\"\n            ],\n            \"lastTransactionID\": \"2319\"\n        }\n    },\n    \"_v3_account_accountID_trades_crcdo\": {\n        \"url\": \"v3/accounts/{accountID}/trades/{tradeID}/close\",\n        \"body\": {\n            \"takeProfit\": {\n                \"timeInForce\": \"GTC\",\n                \"price\": \"1.05\"\n            },\n            \"stopLoss\": {\n                \"timeInForce\": \"GTC\",\n                \"price\": \"1.10\"\n            }\n        },\n        \"response\": {\n            \"stopLossOrderTransaction\": {\n                \"timeInForce\": \"GTC\",\n                \"triggerCondition\": \"TRIGGER_DEFAULT\",\n                \"replacesOrderID\": \"2324\",\n                \"tradeID\": \"2323\",\n                \"price\": \"1.10000\",\n                \"userID\": 1435156,\n                \"batchID\": \"2325\",\n                \"reason\": \"REPLACEMENT\",\n                \"time\": \"2016-10-28T21:00:19.978476830Z\",\n                \"cancellingTransactionID\": \"2326\",\n                \"type\": \"STOP_LOSS_ORDER\",\n                \"id\": \"2327\",\n                \"accountID\": \"101-004-1435156-001\"\n            },\n            \"takeProfitOrderTransaction\": {\n                \"timeInForce\": \"GTC\",\n                \"triggerCondition\": \"TRIGGER_DEFAULT\",\n                \"tradeID\": \"2323\",\n                \"price\": \"1.05000\",\n                \"userID\": 1435156,\n                \"batchID\": \"2325\",\n                \"reason\": \"CLIENT_ORDER\",\n                \"time\": \"2016-10-28T21:00:19.978476830Z\",\n                \"type\": \"TAKE_PROFIT_ORDER\",\n                \"id\": \"2325\",\n                \"accountID\": \"101-004-1435156-001\"\n            },\n            \"relatedTransactionIDs\": [\n                \"2325\",\n                \"2326\",\n                \"2327\"\n            ],\n            \"lastTransactionID\": \"2327\",\n            \"stopLossOrderCancelTransaction\": {\n                \"orderID\": \"2324\",\n                \"replacedByOrderID\": \"2327\",\n                \"userID\": 1435156,\n                \"batchID\": \"2325\",\n                \"reason\": \"CLIENT_REQUEST_REPLACED\",\n                \"time\": \"2016-10-28T21:00:19.978476830Z\",\n                \"type\": \"ORDER_CANCEL\",\n                \"id\": \"2326\",\n                \"accountID\": \"101-004-1435156-001\"\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "oandapyV20/endpoints/responses/transactions.py",
    "content": "\"\"\"Responses.\n\nresponses serve both testing purpose aswell as dynamic docstring replacement\n\"\"\"\nresponses = {\n    \"_v3_accounts_accountID_transactions\": {\n        \"url\": \"v3/accounts/{accountID}/transactions\",\n        \"params\": {\n            \"pageSize\": 200\n        },\n        \"response\": {\n            \"count\": 2124,\n            \"from\": \"2016-06-24T21:03:50.914647476Z\",\n            \"lastTransactionID\": \"2124\",\n            \"pageSize\": 100,\n            \"to\": \"2016-10-05T06:54:14.025946546Z\",\n            \"pages\": [\n                \"https://api-fxpractice.oanda.com/v3/accounts/\"\n                \"101-004-1435156-001/transactions/idrange?from=1&to=100\",\n                \"https://api-fxpractice.oanda.com/v3/accounts/\"\n                \"101-004-1435156-001/transactions/idrange?from=101&to=200\",\n                \"https://api-fxpractice.oanda.com/v3/accounts/\"\n                \"101-004-1435156-001/transactions/idrange?from=201&to=300\",\n                \"https://api-fxpractice.oanda.com/v3/accounts/\"\n                \"101-004-1435156-001/transactions/idrange?from=301&to=400\",\n                \"https://api-fxpractice.oanda.com/v3/accounts/\"\n                \"101-004-1435156-001/transactions/idrange?from=401&to=500\",\n                \"https://api-fxpractice.oanda.com/v3/accounts/\"\n                \"101-004-1435156-001/transactions/idrange?from=501&to=600\",\n                \"https://api-fxpractice.oanda.com/v3/accounts/\"\n                \"101-004-1435156-001/transactions/idrange?from=601&to=700\",\n                \"https://api-fxpractice.oanda.com/v3/accounts/\"\n                \"101-004-1435156-001/transactions/idrange?from=701&to=800\",\n                \"https://api-fxpractice.oanda.com/v3/accounts/\"\n                \"101-004-1435156-001/transactions/idrange?from=801&to=900\",\n                \"https://api-fxpractice.oanda.com/v3/accounts/\"\n                \"101-004-1435156-001/transactions/idrange?from=901&to=1000\",\n                \"https://api-fxpractice.oanda.com/v3/accounts/\"\n                \"101-004-1435156-001/transactions/idrange?from=1001&to=1100\",\n                \"https://api-fxpractice.oanda.com/v3/accounts/\"\n                \"101-004-1435156-001/transactions/idrange?from=1101&to=1200\",\n                \"https://api-fxpractice.oanda.com/v3/accounts/\"\n                \"101-004-1435156-001/transactions/idrange?from=1201&to=1300\",\n                \"https://api-fxpractice.oanda.com/v3/accounts/\"\n                \"101-004-1435156-001/transactions/idrange?from=1301&to=1400\",\n                \"https://api-fxpractice.oanda.com/v3/accounts/\"\n                \"101-004-1435156-001/transactions/idrange?from=1401&to=1500\",\n                \"https://api-fxpractice.oanda.com/v3/accounts/\"\n                \"101-004-1435156-001/transactions/idrange?from=1501&to=1600\",\n                \"https://api-fxpractice.oanda.com/v3/accounts/\"\n                \"101-004-1435156-001/transactions/idrange?from=1601&to=1700\",\n                \"https://api-fxpractice.oanda.com/v3/accounts/\"\n                \"101-004-1435156-001/transactions/idrange?from=1701&to=1800\",\n                \"https://api-fxpractice.oanda.com/v3/accounts/\"\n                \"101-004-1435156-001/transactions/idrange?from=1801&to=1900\",\n                \"https://api-fxpractice.oanda.com/v3/accounts/\"\n                \"101-004-1435156-001/transactions/idrange?from=1901&to=2000\",\n                \"https://api-fxpractice.oanda.com/v3/accounts/\"\n                \"101-004-1435156-001/transactions/idrange?from=2001&to=2100\",\n                \"https://api-fxpractice.oanda.com/v3/accounts/\"\n                \"101-004-1435156-001/transactions/idrange?from=2101&to=2124\"\n            ]\n        }\n    },\n    \"_v3_accounts_transaction_details\": {\n        \"url\": \"v3/accounts/{accountID}/transactions/{transactionID}\",\n        \"response\": {\n            \"transaction\": {\n                \"timeInForce\": \"GTC\",\n                \"triggerCondition\": \"TRIGGER_DEFAULT\",\n                \"positionFill\": \"DEFAULT\",\n                \"stopLossOnFill\": {\n                    \"timeInForce\": \"GTC\",\n                    \"price\": \"1.22000\"\n                },\n                \"userID\": 1435156,\n                \"id\": \"2304\",\n                \"batchID\": \"2304\",\n                \"instrument\": \"EUR_USD\",\n                \"reason\": \"CLIENT_ORDER\",\n                \"time\": \"2016-10-24T21:48:18.593753865Z\",\n                \"units\": \"-100\",\n                \"type\": \"LIMIT_ORDER\",\n                \"price\": \"1.20000\",\n                \"accountID\": \"101-004-1435156-001\"\n            },\n            \"lastTransactionID\": \"2311\"\n        }\n    },\n    \"_v3_accounts_transaction_idrange\": {\n        \"url\": \"v3/accounts/{accountID}/transactions/idrange\",\n        \"params\": {\n            \"from\": 2304,\n            \"to\": 2306\n        },\n        \"response\": {\n            \"lastTransactionID\": \"2311\",\n            \"transactions\": [\n                {\n                    \"timeInForce\": \"GTC\",\n                    \"triggerCondition\": \"TRIGGER_DEFAULT\",\n                    \"positionFill\": \"DEFAULT\",\n                    \"stopLossOnFill\": {\n                      \"timeInForce\": \"GTC\",\n                      \"price\": \"1.22000\"\n                    },\n                    \"userID\": 1435156,\n                    \"id\": \"2304\",\n                    \"batchID\": \"2304\",\n                    \"instrument\": \"EUR_USD\",\n                    \"reason\": \"CLIENT_ORDER\",\n                    \"time\": \"2016-10-24T21:48:18.593753865Z\",\n                    \"units\": \"-100\",\n                    \"type\": \"LIMIT_ORDER\",\n                    \"price\": \"1.20000\",\n                    \"accountID\": \"101-004-1435156-001\"\n                },\n                {\n                    \"orderID\": \"2304\",\n                    \"userID\": 1435156,\n                    \"batchID\": \"2305\",\n                    \"clientExtensionsModify\": {\n                      \"comment\": \"myComment\",\n                      \"id\": \"myID\"\n                    },\n                    \"time\": \"2016-10-25T15:56:43.075594239Z\",\n                    \"type\": \"ORDER_CLIENT_EXTENSIONS_MODIFY\",\n                    \"id\": \"2305\",\n                    \"accountID\": \"101-004-1435156-001\"\n                },\n                {\n                    \"orderID\": \"2304\",\n                    \"clientOrderID\": \"myID\",\n                    \"replacedByOrderID\": \"2307\",\n                    \"userID\": 1435156,\n                    \"batchID\": \"2306\",\n                    \"reason\": \"CLIENT_REQUEST_REPLACED\",\n                    \"time\": \"2016-10-25T19:45:38.558056359Z\",\n                    \"type\": \"ORDER_CANCEL\",\n                    \"id\": \"2306\",\n                    \"accountID\": \"101-004-1435156-001\"\n                }\n            ]\n        }\n    },\n    \"_v3_accounts_transaction_sinceid\": {\n        \"url\": \"v3/accounts/{accountID}/transactions/sinceid\",\n        \"params\": {\n            \"id\": 2306\n        },\n        \"response\": {\n            \"lastTransactionID\": \"2311\",\n            \"transactions\": [\n                {\n                  \"timeInForce\": \"GTC\",\n                  \"triggerCondition\": \"TRIGGER_DEFAULT\",\n                  \"replacesOrderID\": \"2304\",\n                  \"positionFill\": \"DEFAULT\",\n                  \"userID\": 1435156,\n                  \"units\": \"-500000\",\n                  \"batchID\": \"2306\",\n                  \"instrument\": \"EUR_USD\",\n                  \"reason\": \"REPLACEMENT\",\n                  \"time\": \"2016-10-25T19:45:38.558056359Z\",\n                  \"price\": \"1.25000\",\n                  \"clientExtensions\": {\n                    \"comment\": \"myComment\",\n                    \"id\": \"myID\"\n                  },\n                  \"type\": \"LIMIT_ORDER\",\n                  \"id\": \"2307\",\n                  \"accountID\": \"101-004-1435156-001\"\n                },\n                {\n                  \"orderID\": \"2307\",\n                  \"clientOrderID\": \"myID\",\n                  \"userID\": 1435156,\n                  \"batchID\": \"2308\",\n                  \"reason\": \"CLIENT_REQUEST\",\n                  \"time\": \"2016-10-25T20:53:03.789670387Z\",\n                  \"type\": \"ORDER_CANCEL\",\n                  \"id\": \"2308\",\n                  \"accountID\": \"101-004-1435156-001\"\n                },\n                {\n                  \"timeInForce\": \"GTC\",\n                  \"triggerCondition\": \"TRIGGER_DEFAULT\",\n                  \"positionFill\": \"DEFAULT\",\n                  \"stopLossOnFill\": {\n                    \"timeInForce\": \"GTC\",\n                    \"price\": \"1.22000\"\n                  },\n                  \"userID\": 1435156,\n                  \"id\": \"2309\",\n                  \"batchID\": \"2309\",\n                  \"instrument\": \"EUR_USD\",\n                  \"reason\": \"CLIENT_ORDER\",\n                  \"time\": \"2016-10-25T21:07:21.065554321Z\",\n                  \"units\": \"-100\",\n                  \"type\": \"LIMIT_ORDER\",\n                  \"price\": \"1.20000\",\n                  \"accountID\": \"101-004-1435156-001\"\n                },\n                {\n                  \"userID\": 1435156,\n                  \"marginRate\": \"0.01\",\n                  \"batchID\": \"2310\",\n                  \"time\": \"2016-10-26T13:28:00.507651360Z\",\n                  \"type\": \"CLIENT_CONFIGURE\",\n                  \"id\": \"2310\",\n                  \"accountID\": \"101-004-1435156-001\"\n                },\n                {\n                  \"userID\": 1435156,\n                  \"marginRate\": \"0.01\",\n                  \"batchID\": \"2311\",\n                  \"time\": \"2016-10-26T13:28:13.597103123Z\",\n                  \"type\": \"CLIENT_CONFIGURE\",\n                  \"id\": \"2311\",\n                  \"accountID\": \"101-004-1435156-001\"\n                }\n            ]\n        }\n    },\n    \"_v3_accounts_transactions_stream\": {\n        \"url\": \"v3/accounts/{accountID}/transactions/stream\",\n        \"response\": [\n            {\n                \"type\": \"HEARTBEAT\",\n                \"lastTransactionID\": \"2311\",\n                \"time\": \"2016-10-28T11:56:12.002855862Z\"\n            },\n            {\n                \"type\": \"HEARTBEAT\",\n                \"lastTransactionID\": \"2311\",\n                \"time\": \"2016-10-28T11:56:17.059535527Z\"\n            },\n            {\n                \"type\": \"HEARTBEAT\",\n                \"lastTransactionID\": \"2311\",\n                \"time\": \"2016-10-28T11:56:22.142256403Z\"\n            },\n            {\n                \"type\": \"HEARTBEAT\",\n                \"lastTransactionID\": \"2311\",\n                \"time\": \"2016-10-28T11:56:27.238853774Z\"\n            },\n            {\n                \"type\": \"HEARTBEAT\",\n                \"lastTransactionID\": \"2311\",\n                \"time\": \"2016-10-28T11:56:32.289316796Z\"\n            }\n        ]\n    }\n}\n"
  },
  {
    "path": "oandapyV20/endpoints/trades.py",
    "content": "# -*- coding: utf-8 -*-\n\"\"\"Handle trades endpoints.\"\"\"\nfrom .apirequest import APIRequest\nfrom .decorators import dyndoc_insert, endpoint\nfrom .responses.trades import responses\nfrom abc import abstractmethod\n\n\nclass Trades(APIRequest):\n    \"\"\"Trades - abstract baseclass to handle the trades endpoints.\"\"\"\n\n    ENDPOINT = \"\"\n    METHOD = \"GET\"\n\n    @abstractmethod\n    @dyndoc_insert(responses)\n    def __init__(self, accountID, tradeID=None):\n        \"\"\"Instantiate a Trades APIRequest instance.\n\n        Parameters\n        ----------\n        accountID : string\n            the account_id of the account.\n\n        tradeID : string\n            ID of the trade\n\n        \"\"\"\n        endpoint = self.ENDPOINT.format(accountID=accountID, tradeID=tradeID)\n        super(Trades, self).__init__(endpoint, method=self.METHOD)\n\n\n@endpoint(\"v3/accounts/{accountID}/trades\")\nclass TradesList(Trades):\n    \"\"\"Get a list of trades for an Account.\"\"\"\n\n    @dyndoc_insert(responses)\n    def __init__(self, accountID, params=None):\n        \"\"\"Instantiate a TradesList request.\n\n        Parameters\n        ----------\n        accountID : string (required)\n            id of the account to perform the request on.\n\n        params : dict (optional)\n            query params to send, check developer.oanda.com for details.\n\n\n        Query Params example::\n\n            {_v3_accounts_accountID_trades_params}\n\n\n        >>> import oandapyV20\n        >>> import oandapyV20.endpoints.trades as trades\n        >>> client = oandapyV20.API(access_token=...)\n        >>> params = {_v3_accounts_accountID_trades_params}\n        >>> r = trades.TradesList(accountID=..., params=params)\n        >>> client.request(r)\n        >>> print r.response\n\n        Output::\n\n            {_v3_accounts_accountID_trades_resp}\n\n        \"\"\"\n        super(TradesList, self).__init__(accountID)\n        self.params = params\n\n\n@endpoint(\"v3/accounts/{accountID}/openTrades\")\nclass OpenTrades(Trades):\n    \"\"\"Get the list of open Trades for an Account.\"\"\"\n\n    @dyndoc_insert(responses)\n    def __init__(self, accountID):\n        \"\"\"Instantiate an OpenTrades request.\n\n        Parameters\n        ----------\n        accountID : string (required)\n            id of the account to perform the request on.\n\n\n        >>> import oandapyV20\n        >>> import oandapyV20.endpoints.trades as trades\n        >>> client = oandapyV20.API(access_token=...)\n        >>> r = trades.OpenTrades(accountID=...)\n        >>> client.request(r)\n        >>> print r.response\n\n\n        Output::\n\n            {_v3_accounts_accountID_opentrades_resp}\n\n        \"\"\"\n        super(OpenTrades, self).__init__(accountID)\n\n\n@endpoint(\"v3/accounts/{accountID}/trades/{tradeID}\")\nclass TradeDetails(Trades):\n    \"\"\"Get the details of a specific Trade in an Account.\"\"\"\n\n    @dyndoc_insert(responses)\n    def __init__(self, accountID, tradeID):\n        \"\"\"Instantiate a TradeDetails request.\n\n        Parameters\n        ----------\n        accountID : string (required)\n            id of the account to perform the request on.\n\n        tradeID : string (required)\n            id of the trade.\n\n\n        >>> import oandapyV20\n        >>> import oandapyV20.endpoints.trades as trades\n        >>> client = oandapyV20.API(access_token=...)\n        >>> r = trades.TradeDetails(accountID=..., tradeID=...)\n        >>> client.request(r)\n        >>> print r.response\n\n\n        Output::\n\n            {_v3_account_accountID_trades_details_resp}\n\n        \"\"\"\n        super(TradeDetails, self).__init__(accountID, tradeID)\n\n\n@endpoint(\"v3/accounts/{accountID}/trades/{tradeID}/close\", \"PUT\")\nclass TradeClose(Trades):\n    \"\"\"TradeClose.\n\n    Close (partially or fully) a specific open Trade in an Account.\n    \"\"\"\n\n    HEADERS = {\"Content-Type\": \"application/json\"}\n\n    @dyndoc_insert(responses)\n    def __init__(self, accountID, tradeID, data=None):\n        \"\"\"Instantiate a TradeClose request.\n\n        Parameters\n        ----------\n        accountID : string (required)\n            id of the account to perform the request on.\n\n        tradeID : string (required)\n            id of the trade to close.\n\n        data : dict (optional)\n            data to send, use this to close a trade partially. Check\n            developer.oanda.com for details.\n\n\n        Data body example::\n\n            {_v3_account_accountID_trades_close_body}\n\n\n        >>> import oandapyV20\n        >>> import oandapyV20.endpoints.trades as trades\n        >>> client = oandapyV20.API(access_token=...)\n        >>> data = {_v3_account_accountID_trades_close_body}\n        >>> r = trades.TradeClose(accountID=..., data=data)\n        >>> client.request(r)\n        >>> print r.response\n\n        Output::\n\n            {_v3_account_accountID_trades_close_resp}\n\n        \"\"\"\n        super(TradeClose, self).__init__(accountID, tradeID)\n        self.data = data\n\n\n@endpoint(\"v3/accounts/{accountID}/trades/{tradeID}/clientExtensions\", \"PUT\")\nclass TradeClientExtensions(Trades):\n    \"\"\"TradeClientExtensions.\n\n    Update the Client Extensions for a Trade. Do not add, update or delete\n    the Client Extensions if your account is associated with MT4.\n    \"\"\"\n\n    HEADERS = {\"Content-Type\": \"application/json\"}\n\n    @dyndoc_insert(responses)\n    def __init__(self, accountID, tradeID, data=None):\n        \"\"\"Instantiate a TradeClientExtensions request.\n\n        Parameters\n        ----------\n        accountID : string (required)\n            id of the account to perform the request on.\n\n        tradeID : string (required)\n            id of the trade to update client extensions for.\n\n        data : dict (required)\n            clientextension data to send, check developer.oanda.com\n            for details.\n\n\n        Data body example::\n\n            {_v3_account_accountID_trades_cltext_body}\n\n\n        >>> import oandapyV20\n        >>> import oandapyV20.endpoints.trades as trades\n        >>> accountID = ...\n        >>> tradeID = ...\n        >>> client = oandapyV20.API(access_token=...)\n        >>> data = {_v3_account_accountID_trades_cltext_body}\n        >>> r = trades.TradeClientExtensions(accountID=accountID,\n        >>>                                  tradeID=tradeID,\n        >>>                                  data=data)\n        >>> client.request(r)\n        >>> print r.response\n\n        Output::\n\n            {_v3_account_accountID_trades_cltext_resp}\n\n        \"\"\"\n        super(TradeClientExtensions, self).__init__(accountID, tradeID)\n        self.data = data\n\n\n@endpoint(\"v3/accounts/{accountID}/trades/{tradeID}/orders\", \"PUT\")\nclass TradeCRCDO(Trades):\n    \"\"\"Trade Create Replace Cancel Dependent Orders.\"\"\"\n\n    HEADERS = {\"Content-Type\": \"application/json\"}\n\n    @dyndoc_insert(responses)\n    def __init__(self, accountID, tradeID, data):\n        \"\"\"Instantiate a TradeClientExtensions request.\n\n        Parameters\n        ----------\n        accountID : string (required)\n            id of the account to perform the request on.\n\n        tradeID : string (required)\n            id of the trade to update client extensions for.\n\n        data : dict (required)\n            clientextension data to send, check developer.oanda.com\n            for details.\n\n\n        Data body example::\n\n            {_v3_account_accountID_trades_crcdo_body}\n\n\n        >>> import oandapyV20\n        >>> import oandapyV20.endpoints.trades as trades\n        >>> accountID = ...\n        >>> tradeID = ...\n        >>> client = oandapyV20.API(access_token=...)\n        >>> data = {_v3_account_accountID_trades_crcdo_body}\n        >>> r = trades.TradeCRCDO(accountID=accountID,\n        >>>                       tradeID=tradeID,\n        >>>                       data=data)\n        >>> client.request(r)\n        >>> print r.response\n\n        Output::\n\n            {_v3_account_accountID_trades_crcdo_resp}\n\n        \"\"\"\n        super(TradeCRCDO, self).__init__(accountID, tradeID)\n        self.data = data\n"
  },
  {
    "path": "oandapyV20/endpoints/transactions.py",
    "content": "# -*- coding: utf-8 -*-\n\"\"\"Handle transactions endpoints.\"\"\"\nfrom .apirequest import APIRequest\nfrom ..exceptions import StreamTerminated\nfrom .decorators import dyndoc_insert, endpoint\nfrom .responses.transactions import responses\nfrom types import GeneratorType\nfrom abc import abstractmethod\n\n\nclass Transactions(APIRequest):\n    \"\"\"Transactions - abstract baseclass to handle transaction endpoints.\"\"\"\n\n    ENDPOINT = \"\"\n    METHOD = \"GET\"\n\n    @abstractmethod\n    @dyndoc_insert(responses)\n    def __init__(self, accountID, transactionID=None):\n        \"\"\"Instantiate a Transactions APIRequest instance.\n\n        Parameters\n        ----------\n        accountID : string (required)\n            the id of the account.\n\n        transactionID : string\n            the id of the transaction\n\n        \"\"\"\n        endpoint = self.ENDPOINT.format(accountID=accountID,\n                                        transactionID=transactionID)\n        super(Transactions, self).__init__(endpoint,\n                                           method=self.METHOD)\n\n\n@endpoint(\"v3/accounts/{accountID}/transactions\")\nclass TransactionList(Transactions):\n    \"\"\"TransactionList.\n\n    Get a list of Transactions pages that satisfy a time-based Transaction\n    query.\n    \"\"\"\n\n    @dyndoc_insert(responses)\n    def __init__(self, accountID, params=None):\n        \"\"\"Instantiate a TransactionList request.\n\n        Parameters\n        ----------\n        accountID : string (required)\n            id of the account to perform the request on.\n\n        params : dict (optional)\n            query params to send, check developer.oanda.com for details.\n\n\n        Query Params example::\n\n           {_v3_accounts_accountID_transactions_params}\n\n        >>> import oandapyV20\n        >>> import oandapyV20.endpoints.transactions as trans\n        >>> client = oandapyV20.API(access_token=...)\n        >>> r = trans.TransactionList(accountID)  # params optional\n        >>> client.request(r)\n        >>> print r.response\n\n        Output::\n\n           {_v3_accounts_accountID_transactions_resp}\n\n        \"\"\"\n        super(TransactionList, self).__init__(accountID)\n        self.params = params\n\n\n@endpoint(\"v3/accounts/{accountID}/transactions/{transactionID}\")\nclass TransactionDetails(Transactions):\n    \"\"\"Get the details of a single Account Transaction.\"\"\"\n\n    @dyndoc_insert(responses)\n    def __init__(self, accountID, transactionID):\n        \"\"\"Instantiate a TransactionDetails request.\n\n        Parameters\n        ----------\n        accountID : string (required)\n            id of the account to perform the request on.\n\n        transactionID : string (required)\n            id of the transaction\n\n\n        >>> import oandapyV20\n        >>> import oandapyV20.endpoints.transactions as trans\n        >>> client = oandapyV20.API(access_token=...)\n        >>> r = trans.TransactionDetails(accountID=..., transactionID=...)\n        >>> client.request(r)\n        >>> print r.response\n\n        Output::\n\n           {_v3_accounts_transaction_details_resp}\n\n        \"\"\"\n        super(TransactionDetails, self).__init__(accountID, transactionID)\n\n\n@endpoint(\"v3/accounts/{accountID}/transactions/idrange\")\nclass TransactionIDRange(Transactions):\n    \"\"\"TransactionIDRange.\n\n    Get a range of Transactions for an Account based on Transaction IDs.\n    \"\"\"\n\n    @dyndoc_insert(responses)\n    def __init__(self, accountID, params=None):\n        \"\"\"Instantiate an TransactionIDRange request.\n\n        Parameters\n        ----------\n        accountID : string (required)\n            id of the account to perform the request on.\n\n        params : dict (required)\n            query params to send, check developer.oanda.com for details.\n\n\n        Query Params example::\n\n            {_v3_accounts_transaction_idrange_params}\n\n\n        >>> import oandapyV20\n        >>> import oandapyV20.endpoints.transactions as trans\n        >>> client = oandapyV20.API(access_token=...)\n        >>> params = {_v3_accounts_transaction_idrange_params}\n        >>> r = trans.TransactionIDRange(accountID=..., params=params)\n        >>> client.request(r)\n        >>> print r.response\n\n        Output::\n\n            {_v3_accounts_transaction_idrange_resp}\n\n        \"\"\"\n        super(TransactionIDRange, self).__init__(accountID)\n        self.params = params\n\n\n@endpoint(\"v3/accounts/{accountID}/transactions/sinceid\")\nclass TransactionsSinceID(Transactions):\n    \"\"\"TransactionsSinceID.\n\n    Get a range of Transactions for an Account starting at (but not including)\n    a provided Transaction ID.\n    \"\"\"\n\n    @dyndoc_insert(responses)\n    def __init__(self, accountID, params=None):\n        \"\"\"Instantiate an TransactionsSince request.\n\n        Parameters\n        ----------\n        accountID : string (required)\n            id of the account to perform the request on.\n\n        params : dict (required)\n            query params to send, check developer.oanda.com for details.\n\n\n        Query Params example::\n\n            {_v3_accounts_transaction_sinceid_params}\n\n\n        >>> import oandapyV20\n        >>> import oandapyV20.endpoints.transactions as trans\n        >>> client = oandapyV20.API(access_token=...)\n        >>> params = {_v3_accounts_transaction_sinceid_params}\n        >>> r = trans.TransactionsSinceID(accountID=..., params=params)\n        >>> client.request(r)\n        >>> print r.response\n\n        Output::\n\n            {_v3_accounts_transaction_sinceid_resp}\n\n        \"\"\"\n        super(TransactionsSinceID, self).__init__(accountID)\n        self.params = params\n\n\n@endpoint(\"v3/accounts/{accountID}/transactions/stream\")\nclass TransactionsStream(Transactions):\n    \"\"\"TransactionsStream.\n\n    Get a stream of Transactions for an Account starting from when the\n    request is made.\n    \"\"\"\n\n    STREAM = True\n\n    @dyndoc_insert(responses)\n    def __init__(self, accountID, params=None):\n        \"\"\"Instantiate an TransactionsStream request.\n\n        Performing this request will result in a generator yielding\n        transactions.\n\n        Parameters\n        ----------\n        accountID : string (required)\n            id of the account to perform the request on.\n\n\n        >>> import oandapyV20\n        >>> import oandapyV20.endpoints.transactions as trans\n        >>> client = oandapyV20.API(access_token=...)\n        >>> r = trans.TransactionsStream(accountID=...)\n        >>> rv = client.request(r)\n        >>> maxrecs = 5\n        >>> try:\n        >>>     for T in r.response:  # or rv ...\n        >>>         print json.dumps(R, indent=4), \",\"\n        >>>         maxrecs -= 1\n        >>>         if maxrecs == 0:\n        >>>             r.terminate(\"Got them all\")\n        >>> except StreamTerminated as e:\n        >>>    print(\"Finished: {{msg}}\".format(msg=e))\n\n        Output::\n\n            {_v3_accounts_transactions_stream_ciresp}\n\n            Finished: Got them all\n\n        \"\"\"\n        super(TransactionsStream, self).__init__(accountID)\n        self.params = params\n\n    def terminate(self, message=\"\"):\n        \"\"\"terminate the stream.\n\n        Calling this method will stop the generator yielding transaction\n        records. A message can be passed optionally.\n        \"\"\"\n        if not isinstance(self.response, GeneratorType):\n            raise ValueError(\"request does not contain a stream response\")\n\n        self.response.throw(StreamTerminated(message))\n"
  },
  {
    "path": "oandapyV20/exceptions.py",
    "content": "\"\"\"Exceptions.\"\"\"\n\n\nclass StreamTerminated(Exception):\n    \"\"\"StreamTerminated.\"\"\"\n\n\nclass V20Error(Exception):\n    \"\"\"Generic error class.\n\n    In case of HTTP response codes >= 400 this class can be used\n    to raise an exception representing that error.\n    \"\"\"\n\n    def __init__(self, code, msg):\n        \"\"\"Instantiate a V20Error.\n\n        Parameters\n        ----------\n        code : int\n            the HTTP-code of the response\n\n        msg : str\n            the message returned with the response\n        \"\"\"\n        self.code = code\n        self.msg = msg\n\n        super(V20Error, self).__init__(msg)\n"
  },
  {
    "path": "oandapyV20/oandapyV20.py",
    "content": "# -*- coding: utf-8 -*-\n\"\"\"OANDA API wrapper for OANDA's REST-V20 API.\"\"\"\n\nimport json\nimport requests\nimport logging\nfrom .exceptions import V20Error\n\nITER_LINES_CHUNKSIZE = 60\n\nTRADING_ENVIRONMENTS = {\n    \"practice\": {\n        \"stream\": 'https://stream-fxpractice.oanda.com',\n        \"api\": 'https://api-fxpractice.oanda.com'\n    },\n    \"live\": {\n        \"stream\": 'https://stream-fxtrade.oanda.com',\n        \"api\": 'https://api-fxtrade.oanda.com'\n    }\n}\n\nDEFAULT_HEADERS = {\n    \"Accept-Encoding\": \"gzip, deflate\"\n}\n\nlogger = logging.getLogger(__name__)\n\n\nclass API(object):\n    r\"\"\"API - class to handle APIRequests objects to access API endpoints.\n\n    Examples\n    --------\n\n    ::\n\n        # get a list of trades\n        from oandapyV20 import API\n        import oandapyV20.endpoints.trades as trades\n\n        api = API(access_token=\"xxx\")\n        accountID = \"101-305-3091856-001\"\n\n        r = trades.TradesList(accountID)\n        # show the endpoint as it is constructed for this call\n        print(\"REQUEST:{}\".format(r))\n        rv = api.request(r)\n        print(\"RESPONSE:\\n{}\".format(json.dumps(rv, indent=2)))\n\n\n    Output::\n\n        REQUEST:v3/accounts/101-305-3091856-001/trades\n        RESPONSE:\n        \"trades\": [\n            {\n              \"financing\": \"0.0000\",\n              \"openTime\": \"2016-07-21T15:47:05.170212014Z\",\n              \"price\": \"10133.9\",\n              \"unrealizedPL\": \"8.0000\",\n              \"realizedPL\": \"0.0000\",\n              \"instrument\": \"DE30_EUR\",\n              \"state\": \"OPEN\",\n              \"initialUnits\": \"-10\",\n              \"currentUnits\": \"-10\",\n              \"id\": \"1032\"\n            },\n            {\n              \"financing\": \"0.0000\",\n              \"openTime\": \"2016-07-21T15:47:04.963590941Z\",\n              \"price\": \"10134.4\",\n              \"unrealizedPL\": \"13.0000\",\n              \"realizedPL\": \"0.0000\",\n              \"instrument\": \"DE30_EUR\",\n              \"state\": \"OPEN\",\n              \"initialUnits\": \"-10\",\n              \"currentUnits\": \"-10\",\n              \"id\": \"1030\"\n            }\n          ],\n          \"lastTransactionID\": \"1040\"\n        }\n\n    ::\n\n        # reduce a trade by it's id\n        from oandapyV20 import API\n        import oandapyV20.endpoints.trades as trades\n\n        api = API(access_token=\"...\")\n\n        accountID = \"101-305-3091856-001\"\n        tradeID = \"1030\"\n        cfg = {\"units\": 5}\n        r = trades.TradeClose(accountID, tradeID=tradeID, data=cfg)\n        # show the endpoint as it is constructed for this call\n        print(\"REQUEST:{}\".format(r))\n        rv = api.request(r)\n        print(\"RESPONSE\\n{}\".format(json.dumps(rv, indent=2)))\n\n    or by using it in a *with context*:\n\n    ::\n\n        with API(access_token=\"...\") as api:\n\n            accountID = \"101-305-3091856-001\"\n            tradeID = \"1030\"\n            cfg = {\"units\": 5}\n            r = trades.TradeClose(accountID, tradeID=tradeID, data=cfg)\n            # show the endpoint as it is constructed for this call\n            print(\"REQUEST:{}\".format(r))\n            rv = api.request(r)\n            print(\"RESPONSE\\n{}\".format(json.dumps(rv, indent=2)))\n\n    in this case the API-client instance *api* will close connections\n    explicitely.\n\n    Output::\n\n        REQUEST:v3/accounts/101-305-3091856-001/trades/1030/close\n        RESPONSE: {\n          \"orderFillTransaction\": {\n            \"orderID\": \"1041\",\n            \"financing\": \"-0.1519\",\n            \"instrument\": \"DE30_EUR\",\n            \"userID\": 1435156,\n            \"price\": \"10131.6\",\n            \"tradeReduced\": {\n              \"units\": \"5\",\n              \"financing\": \"-0.1519\",\n              \"realizedPL\": \"14.0000\",\n              \"tradeID\": \"1030\"\n            },\n            \"batchID\": \"1041\",\n            \"accountBalance\": \"44876.2548\",\n            \"reason\": \"MARKET_ORDER_TRADE_CLOSE\",\n            \"time\": \"2016-07-21T17:32:51.361464739Z\",\n            \"units\": \"5\",\n            \"type\": \"ORDER_FILL\",\n            \"id\": \"1042\",\n            \"pl\": \"14.0000\",\n            \"accountID\": \"101-305-3091856-001\"\n          },\n          \"orderCreateTransaction\": {\n            \"timeInForce\": \"FOK\",\n            \"positionFill\": \"REDUCE_ONLY\",\n            \"userID\": 1435156,\n            \"batchID\": \"1041\",\n            \"instrument\": \"DE30_EUR\",\n            \"reason\": \"TRADE_CLOSE\",\n            \"tradeClose\": {\n              \"units\": \"5\",\n              \"tradeID\": \"1030\"\n            },\n            \"time\": \"2016-07-21T17:32:51.361464739Z\",\n            \"units\": \"5\",\n            \"type\": \"MARKET_ORDER\",\n            \"id\": \"1041\",\n            \"accountID\": \"101-305-3091856-001\"\n          },\n          \"relatedTransactionIDs\": [\n            \"1041\",\n            \"1042\"\n          ],\n          \"lastTransactionID\": \"1042\"\n        }\n    \"\"\"\n\n    def __init__(self, access_token, environment=\"practice\",\n                 headers=None, request_params=None):\n        \"\"\"Instantiate an instance of OandaPy's API wrapper.\n\n        Parameters\n        ----------\n        access_token : string\n            Provide a valid access token.\n\n        environment : string\n            Provide the environment for OANDA's REST api. Valid values:\n            'practice' or 'live'. Default: 'practice'.\n\n        headers : dict (optional)\n            Provide request headers to be set for a request.\n\n\n        .. note::\n\n            There is no need to set the 'Content-Type: application/json'\n            for the endpoints that require this header. The API-request\n            classes covering those endpoints will take care of the header.\n\n        request_params : (optional)\n            parameters to be passed to the request. This can be used to apply\n            for instance a timeout value:\n\n               request_params={\"timeout\": 0.1}\n\n            See specs of the requests module for full details of possible\n            parameters.\n\n        .. warning::\n            parameters belonging to a request need to be set on the\n            requestinstance and are NOT passed via the client.\n\n        \"\"\"\n        logger.info(\"setting up API-client for environment %s\", environment)\n        try:\n            TRADING_ENVIRONMENTS[environment]\n\n        except KeyError as err:  # noqa F841\n            logger.error(\"unkown environment %s\", environment)\n            raise KeyError(\"Unknown environment: {}\".format(environment))\n\n        else:\n            self.environment = environment\n\n        self.access_token = access_token\n        self.client = requests.Session()\n        self.client.stream = False\n        self._request_params = request_params if request_params else {}\n\n        # personal token authentication\n        if self.access_token:\n            self.client.headers['Authorization'] = 'Bearer '+self.access_token\n\n        self.client.headers.update(DEFAULT_HEADERS)\n        if headers:\n            self.client.headers.update(headers)\n            logger.info(\"applying headers %s\", \",\".join(headers.keys()))\n\n    def __enter__(self):\n        return self\n\n    def __exit__(self, exc_type, exc_val, exc_tb):\n        self.close()\n\n    def close(self):\n        \"\"\"close.\n\n        explicit close of the session.\n        \"\"\"\n        self.client.close()\n\n    @property\n    def request_params(self):\n        \"\"\"request_params property.\"\"\"\n        return self._request_params\n\n    def __request(self, method, url, request_args, headers=None, stream=False):\n        \"\"\"__request.\n\n        make the actual request. This method is called by the\n        request method in case of 'regular' API-calls. Or indirectly by\n        the__stream_request method if it concerns a 'streaming' call.\n        \"\"\"\n        func = getattr(self.client, method)\n        headers = headers if headers else {}\n        response = None\n        try:\n            logger.info(\"performing request %s\", url)\n            response = func(url, stream=stream, headers=headers,\n                            **request_args)\n        except requests.RequestException as err:\n            logger.error(\"request %s failed [%s]\", url, err)\n            raise err\n\n        # Handle error responses\n        if response.status_code >= 400:\n            logger.error(\"request %s failed [%d,%s]\",\n                         url,\n                         response.status_code,\n                         response.content.decode('utf-8'))\n            raise V20Error(response.status_code,\n                           response.content.decode('utf-8'))\n        return response\n\n    def __stream_request(self, method, url, request_args, headers=None):\n        \"\"\"__stream_request.\n\n        make a 'stream' request. This method is called by\n        the 'request' method after it has determined which\n        call applies: regular or streaming.\n        \"\"\"\n        headers = headers if headers else {}\n        response = self.__request(method, url, request_args,\n                                  headers=headers, stream=True)\n        lines = response.iter_lines(ITER_LINES_CHUNKSIZE)\n        for line in lines:\n            if line:\n                data = json.loads(line.decode(\"utf-8\"))\n                yield data\n\n    def request(self, endpoint):\n        \"\"\"Perform a request for the APIRequest instance 'endpoint'.\n\n        Parameters\n        ----------\n        endpoint : APIRequest\n            The endpoint parameter contains an instance of an APIRequest\n            containing the endpoint, method and optionally other parameters\n            or body data.\n\n        Raises\n        ------\n            V20Error in case of HTTP response code >= 400\n        \"\"\"\n        method = endpoint.method\n        method = method.lower()\n        params = None\n        try:\n            params = getattr(endpoint, \"params\")\n        except AttributeError:\n            # request does not have params\n            params = {}\n\n        headers = {}\n        if hasattr(endpoint, \"HEADERS\"):\n            headers = getattr(endpoint, \"HEADERS\")\n\n        request_args = {}\n        if method == 'get':\n            request_args['params'] = params\n        elif hasattr(endpoint, \"data\") and endpoint.data:\n            request_args['json'] = endpoint.data\n\n        # if any parameter for request then merge them\n        request_args.update(self._request_params)\n\n        # which API to access ?\n        if not (hasattr(endpoint, \"STREAM\") and\n                getattr(endpoint, \"STREAM\") is True):\n            url = \"{}/{}\".format(\n                TRADING_ENVIRONMENTS[self.environment][\"api\"],\n                endpoint)\n\n            response = self.__request(method, url,\n                                      request_args, headers=headers)\n            content = response.content.decode('utf-8')\n            content = json.loads(content)\n\n            # update endpoint\n            endpoint.response = content\n            endpoint.status_code = response.status_code\n\n            return content\n\n        else:\n            url = \"{}/{}\".format(\n                TRADING_ENVIRONMENTS[self.environment][\"stream\"],\n                endpoint)\n            endpoint.response = self.__stream_request(method,\n                                                      url,\n                                                      request_args,\n                                                      headers=headers)\n            return endpoint.response\n"
  },
  {
    "path": "oandapyV20/types/__init__.py",
    "content": "from .types import (\n    AccountID,\n    DateTime,\n    OrderID,\n    TradeID,\n    AccountUnits,\n    PriceValue,\n    Units,\n    ClientID,\n    ClientTag,\n    ClientComment,\n    OrderIdentifier,\n    OrderSpecifier\n)\n\n__all__ = (\n    'AccountID',\n    'DateTime',\n    'OrderID',\n    'TradeID',\n    'AccountUnits',\n    'PriceValue',\n    'Units',\n    'ClientID',\n    'ClientTag',\n    'ClientComment',\n    'OrderIdentifier',\n    'OrderSpecifier'\n)\n"
  },
  {
    "path": "oandapyV20/types/types.py",
    "content": "# -*- coding: utf-8 -*-\n\"\"\"types.\"\"\"\n\nimport six\nimport re\nfrom abc import ABCMeta\nimport datetime as natdatetime  # native datetime\n\n\n@six.add_metaclass(ABCMeta)\nclass OAType(object):\n    \"\"\"baseclass for OANDA types.\"\"\"\n\n    @property\n    def value(self):\n        \"\"\"value property.\"\"\"\n        return self._v\n\n\nclass AccountID(OAType):\n    \"\"\"representation of an AccountID, string value of an Account Identifier.\n\n    Parameters\n    ----------\n\n    accountID : string (required)\n        the accountID of a v20 account\n\n    Example\n    -------\n\n        >>> print AccountID(\"001-011-5838423-001\").value\n\n\n    A ValueError exception is raised in case of an incorrect value.\n    \"\"\"\n\n    def __init__(self, accountID):\n        l = re.match(r\"(?P<siteID>\\d+)-(?P<divisionID>\\d+)\"\n                     \"-(?P<userID>\\d+)-(?P<accountNumber>\\d+)\", accountID)\n        if not l:\n            msg = \"AccountID {} not a valid V20 account\".format(accountID)\n            raise ValueError(msg)\n\n        self._v = l.groupdict()\n\n\nclass OrderID(OAType):\n    \"\"\"representation of an orderID, string value of an integer.\n\n    Parameters\n    ----------\n\n    orderID : integer or string (required)\n        the orderID as a positive integer or as a string\n\n    Example\n    -------\n\n        >>> print OrderID(1234).value\n\n\n    A ValueError exception is raised in case of a negative integer value\n    \"\"\"\n\n    def __init__(self, orderID):\n        if int(orderID) < 0:\n            raise ValueError(\"OrderID must be a positive integer value\")\n        self._v = \"{:d}\".format(int(orderID))\n\n\nclass DateTime(OAType):\n    \"\"\"representation of a DateTime as a RFC 3339 string.\n\n    Parameters\n    ----------\n\n    dateTime : string, datetime instance, dict (required)\n        the dateTime parameter must be:\n         - a valid RFC3339 string representing a date-time, or\n         - a dict holding the relevant datetime parts, or\n         - a datetime.datetime instance\n\n    The value property is always RFC3339  datetime string\n\n    Fractional seconds are in microseconds. This compatible with\n    datetime.datetime.\n\n    Example\n    -------\n\n    >>> print DateTime(\"2014-07-02T04:00:00.000000Z\").value\n    >>> print DateTime({\"year\": 2014, \"month\": 12, \"day\": 2,\n    ...                 \"hour\": 13, \"minute\": 48, \"second\": 12}).value\n    >>> from datetime import datetime\n    >>> print DateTime(datetime.now()).value\n\n\n    A ValueError exception is raised in case of an invalid value\n    \"\"\"\n\n    def __init__(self, dateTime):\n\n        def formatDT(dtd):\n\n            _date = natdatetime.datetime(\n                int(dtd.get(\"year\")),\n                int(dtd.get(\"month\")),\n                int(dtd.get(\"day\")),\n                int(dtd.get(\"hour\")),\n                int(dtd.get(\"minute\")),\n                int(dtd.get(\"second\")))\n\n            dt = natdatetime.datetime.strftime(_date, \"%Y-%m-%dT%H:%M:%S\")\n\n            if \"subsecond\" in dtd and dtd.get(\"subsecond\") is not None:\n                dt = \"{}.{:>06d}\".format(dt, int(dtd.get(\"subsecond\")))\n\n            return dt+\"Z\"\n\n        if isinstance(dateTime, str):\n            l = re.match(r\"(?P<year>\\d+)-(?P<month>\\d+)-(?P<day>\\d+)\"\n                         \"T(?P<hour>\\d+):(?P<minute>\\d+):(?P<second>\\d+)\"\n                         \"(?:.(?P<subsecond>\\d{1,6})|)\"\n                         \"Z\",\n                         dateTime)\n\n            if not l:\n                msg = \"Invalid RFC 3339 string: {}\".format(dateTime)\n                raise ValueError(msg)\n\n            # print l.groupdict()\n            self._v = formatDT(l.groupdict())\n\n        elif isinstance(dateTime, dict):\n            self._v = formatDT(dateTime)\n\n        elif isinstance(dateTime, natdatetime.datetime):\n            self._v = formatDT({\"year\": dateTime.year,\n                                \"month\": dateTime.month,\n                                \"day\": dateTime.day,\n                                \"hour\": dateTime.hour,\n                                \"minute\": dateTime.minute,\n                                \"second\": dateTime.second,\n                                \"subsecond\": dateTime.microsecond})\n\n\nclass TradeID(OAType):\n    \"\"\"representation of a tradeID, string value of an integer.\n\n    Parameters\n    ----------\n\n    tradeID : integer or string (required)\n        the tradeID as a positive integer or as a string\n\n    Example\n    -------\n\n        >>> print TradeID(1234).value\n\n\n    A ValueError exception is raised in case of a negative integer value\n    \"\"\"\n\n    def __init__(self, tradeID):\n        if int(tradeID) < 0:\n            raise ValueError(\"TradeID must be a positive integer value\")\n        self._v = \"{:d}\".format(int(tradeID))\n\n\nclass AccountUnits(OAType):\n    \"\"\"representation AccountUnits, string value of a float.\"\"\"\n\n    def __init__(self, units):\n        self._v = \"{:.5f}\".format(float(units))\n\n\nclass PriceValue(OAType):\n    \"\"\"representation PriceValue, string value of a float.\"\"\"\n\n    def __init__(self, priceValue):\n        self._v = \"{:.5f}\".format(float(priceValue))\n\n\nclass Units(OAType):\n    \"\"\"representation Units, string value of an integer or float up to 1 decimal.\"\"\"\n\n    def __init__(self, units):\n        _units = str(units)\n\n        # validate the number\n        if re.fullmatch(r'[+-]{0,1}(\\d+)', _units):\n            self._v = \"{:d}\".format(int(_units))\n\n        elif re.fullmatch(r'[+-]{0,1}\\d+(\\.\\d{0,1})', _units):\n            self._v = \"{:.1f}\".format(float(_units))\n\n        elif re.fullmatch(r'[+-]{0,1}\\d+(\\.\\d{0,2})', _units):\n            self._v = \"{:.2f}\".format(float(_units))\n\n        else:\n            raise ValueError(\"incorrect units: {}\".format(_units))\n\n\nclass ClientID(OAType):\n    \"\"\"representation of ClientID, a string value of max 128 chars.\"\"\"\n\n    def __init__(self, clientID):\n        length = len(clientID)\n        if not length or length > 128:\n            raise ValueError(\"ClientID: length {}\".format(length))\n\n        self._v = clientID\n\n\nclass ClientTag(OAType):\n    \"\"\"representation of ClientTag, a string value of max 128 chars.\"\"\"\n\n    def __init__(self, clientTag):\n        length = len(clientTag)\n        if not length or length > 128:\n            raise ValueError(\"ClientTag: length {}\".format(length))\n\n        self._v = clientTag\n\n\nclass ClientComment(OAType):\n    \"\"\"representation of ClientComment, a string value of max 128 chars.\"\"\"\n\n    def __init__(self, clientComment):\n        length = len(clientComment)\n        if not length or length > 128:\n            raise ValueError(\"ClientComment: length {}\".format(length))\n\n        self._v = clientComment\n\n\nclass OrderIdentifier(OAType):\n    \"\"\"representation of the OrderIdentifier object.\"\"\"\n\n    def __init__(self, orderID, clientID):\n        self._v = {\n            \"orderID\": OrderID(orderID).value,\n            \"clientOrderID\": ClientID(clientID).value\n        }\n\n\nclass OrderSpecifier(OAType):\n    \"\"\"representation of the OrderSpecifier.\"\"\"\n\n    def __init__(self, specifier):\n        if str(specifier).startswith('@'):\n            self._v = ClientID(specifier.lstrip('@')).value\n        else:\n            self._v = OrderID(specifier).value\n"
  },
  {
    "path": "readthedocs.yml",
    "content": "requirements_file: requirements.txt\npython:\n  setup_py_install: true\n"
  },
  {
    "path": "requirements.txt",
    "content": "requests>=2.10\nsix>=1.10\n"
  },
  {
    "path": "setup.py",
    "content": "from setuptools import setup, find_packages\nimport os\nimport sys\nimport re\nimport shutil\n\n\ndef get_version(package):\n    \"\"\"\n    Return package version as listed in `__version__` in `init.py`.\n    \"\"\"\n    init_py = open(os.path.join(package, '__init__.py')).read()\n    return re.search(\"__version__ = ['\\\"]([^'\\\"]+)['\\\"]\", init_py).group(1)\n\n\ndef read_all(f):\n    with open(f) as I:\n        return I.read()\n\nrequirements = map(str.strip, open(\"requirements.txt\").readlines())\n\nversion = get_version('oandapyV20')\n\nif sys.argv[-1] == 'publish':\n    print(\"You probably want to also tag the version now:\")\n    print(\"  git tag -a %s -m 'version %s'\" % (version, version))\n    print(\"  git push --tags\")\n    shutil.rmtree('dist')\n    shutil.rmtree('build')\n    shutil.rmtree('oandapyV20.egg-info')\n    sys.exit()\n\nsetup(name='oandapyV20',\n      version=version,\n      description=\"Python wrapper for the OANDA REST-V20 API\",\n      long_description=read_all(\"README.rst\"),\n      classifiers=[\n            'Programming Language :: Python',\n            'License :: OSI Approved :: MIT License',\n            'Intended Audience :: Developers',\n            'Intended Audience :: Financial and Insurance Industry',\n            'Operating System :: OS Independent',\n            'Development Status :: 3 - Alpha',\n            'Topic :: Software Development :: Libraries :: Python Modules',\n            'Programming Language :: Python',\n            'Programming Language :: Python :: 3.6',\n            'Programming Language :: Python :: 3.7',\n            'Programming Language :: Python :: 3.8',\n            'Programming Language :: Python :: 3.9',\n      ],  # Get from http://pypi.python.org/pypi?%3Aaction=list_classifiers\n      keywords='OANDA FOREX/CFD wrapper REST-V20 API',\n      author='F. Brekeveld',\n      author_email='f.brekeveld@gmail.com',\n      url='http://github.com/hootnot/oanda-api-v20',\n      license='MIT',\n      packages=find_packages(exclude=['ez_setup', 'examples', 'tests']),\n      test_suite=\"tests\",\n      include_package_data=True,\n      zip_safe=False,\n      install_requires=requirements,\n      entry_points=\"\"\"\n      # -*- Entry points: -*-\n      \"\"\",\n      )\n"
  },
  {
    "path": "tests/__init__.py",
    "content": ""
  },
  {
    "path": "tests/account.txt",
    "content": "101-004-1435156-001|EUR\n"
  },
  {
    "path": "tests/test_accounts.py",
    "content": "import sys\nimport unittest\nimport json\nfrom . import unittestsetup\nfrom .unittestsetup import environment as environment\nfrom .unittestsetup import fetchTestData\nimport requests_mock\n\n\ntry:\n    from nose_parameterized import parameterized\nexcept:\n    print(\"*** Please install 'nose_parameterized' to run these tests ***\")\n    exit(0)\n\nfrom oandapyV20 import API\nfrom oandapyV20.exceptions import V20Error\nimport oandapyV20.endpoints.accounts as accounts\nfrom oandapyV20.endpoints.accounts import responses\n\naccess_token = None\naccountID = None\naccount_cur = None\napi = None\n\n\nclass TestAccounts(unittest.TestCase):\n    \"\"\"Tests regarding the accounts endpoints.\"\"\"\n\n    def setUp(self):\n        \"\"\"setup for all tests.\"\"\"\n        global access_token\n        global accountID\n        global account_cur\n        global api\n        # self.maxDiff = None\n        try:\n            accountID, account_cur, access_token = unittestsetup.auth()\n            setattr(sys.modules[\"oandapyV20.oandapyV20\"],\n                    \"TRADING_ENVIRONMENTS\",\n                    {\"practice\": {\n                     \"stream\": \"https://test.com\",\n                     \"api\": \"https://test.com\",\n                     }})\n            api = API(environment=environment,\n                      access_token=access_token,\n                      headers={\"Content-Type\": \"application/json\"})\n            api.api_url = 'https://test.com'\n        except Exception as e:\n            print(\"%s\" % e)\n            exit(0)\n\n    @requests_mock.Mocker()\n    def test__account_list(self, mock_req):\n        \"\"\"get the list of accounts.\"\"\"\n        tid = \"_v3_accounts\"\n        resp, data = fetchTestData(responses, tid)\n        r = accounts.AccountList()\n        mock_req.register_uri('GET',\n                              \"{}/{}\".format(api.api_url, r),\n                              text=json.dumps(resp))\n        result = api.request(r)\n        self.assertTrue(result == resp)\n\n    @requests_mock.Mocker()\n    def test__account_details(self, mock_req):\n        \"\"\"get the details of specified account.\"\"\"\n        tid = \"_v3_account_by_accountID\"\n        resp, data = fetchTestData(responses, tid)\n        r = accounts.AccountDetails(accountID=accountID)\n        mock_req.register_uri('GET',\n                              \"{}/{}\".format(api.api_url, r),\n                              text=json.dumps(resp))\n        result = api.request(r)\n        self.assertTrue(result == resp)\n\n    @parameterized.expand([\n                       (None, 200),\n                       (\"X\", 404, \"Account does not exist\"),\n                         ])\n    @requests_mock.Mocker(kw='mock')\n    def test__get_account_summary(self, accID, status_code,\n                                  fail=None, **kwargs):\n        \"\"\"get the summary of specified account.\"\"\"\n        tid = \"_v3_account_by_accountID_summary\"\n        resp, data = fetchTestData(responses, tid)\n        if not accID:\n            # hack to use the global accountID\n            accID = accountID\n        r = accounts.AccountSummary(accountID=accID)\n        text = fail\n        if not fail:\n            text = json.dumps(resp)\n\n        kwargs['mock'].register_uri('GET',\n                                    \"{}/{}\".format(api.api_url, r),\n                                    text=text,\n                                    status_code=status_code)\n\n        if fail:\n            # The test should raise an exception with code == fail\n            oErr = None\n            with self.assertRaises(V20Error) as oErr:\n                result = api.request(r)\n\n            self.assertTrue(fail in \"{}\".format(oErr.exception))\n        else:\n            result = api.request(r)\n            self.assertTrue(result[\"account\"][\"id\"] == accountID and\n                            result[\"account\"][\"currency\"] == account_cur)\n\n    @requests_mock.Mocker()\n    def test__account_instruments(self, mock_req):\n        \"\"\"get the instruments of specified account.\"\"\"\n        tid = \"_v3_account_by_accountID_instruments\"\n        resp, data, params = fetchTestData(responses, tid)\n        r = accounts.AccountInstruments(accountID=accountID, params=params)\n        mock_req.register_uri('GET',\n                              \"{}/{}\".format(api.api_url, r),\n                              text=json.dumps(resp))\n        result = api.request(r)\n        self.assertTrue(result == resp)\n\n    @requests_mock.Mocker()\n    def test__account_configuration(self, mock_req):\n        \"\"\"set configurable parts of account.\"\"\"\n        tid = \"_v3_accounts_accountID_account_config\"\n        resp, data = fetchTestData(responses, tid)\n        r = accounts.AccountConfiguration(accountID=accountID, data=data)\n        mock_req.register_uri('PATCH',\n                              \"{}/{}\".format(api.api_url, r),\n                              text=json.dumps(resp))\n        result = api.request(r)\n        self.assertTrue(result == resp)\n\n    @requests_mock.Mocker()\n    def test__account_changes(self, mock_get):\n        \"\"\"get account state since ID of transaction.\"\"\"\n        tid = \"_v3_accounts_accountID_account_changes\"\n        resp, data, params = fetchTestData(responses, tid)\n        r = accounts.AccountChanges(accountID=accountID, params=params)\n        mock_get.register_uri('GET',\n                              \"{}/{}\".format(api.api_url, r),\n                              text=json.dumps(resp))\n        result = api.request(r)\n        self.assertTrue(result == resp)\n\n\nif __name__ == \"__main__\":\n\n    unittest.main()\n"
  },
  {
    "path": "tests/test_contrib_factories.py",
    "content": "import math\nimport unittest\n\ntry:\n    from nose_parameterized import parameterized\nexcept ImportError:\n    print(\"*** Please install 'nose_parameterized' to run these tests ***\")\n    exit(0)\n\n\nimport oandapyV20.contrib.factories as req\n\n\nclass TestContribFactories(unittest.TestCase):\n    \"\"\"Tests regarding contrib factories.\n\n    The reference is created using the second dict parameter. The\n    first dict parameter is merge with this, but only for the keys\n    that do NOT exist. That allows us to override parameters.\n    The result should reflect the data constructed by the class\n\n    \"\"\"\n\n    @parameterized.expand([\n       (req.InstrumentsCandlesFactory,\n           \"DE30_EUR\",\n           {},\n           {\"len\": 1},\n        ),\n       (req.InstrumentsCandlesFactory,\n           \"DE30_EUR\",\n           {\"from\": \"2017-01-01T00:00:00Z\",\n            \"to\": \"2017-01-02T00:00:00Z\",\n            \"granularity\": \"M1\"},\n           {\"len\": int(math.ceil(24*60.0 / 500))},\n        ),\n       (req.InstrumentsCandlesFactory,\n           \"DE30_EUR\",\n           {\"from\": \"2017-01-01T00:00:00Z\",\n            \"granularity\": \"M1\"},\n           {},\n        ),\n       (req.InstrumentsCandlesFactory,\n           \"DE30_EUR\",\n           {\"from\": \"2017-01-01T00:00:00Z\",\n            \"to\": \"2022-06-30T00:00:00Z\",\n            \"granularity\": \"M1\"},\n           {},\n        ),\n       (req.InstrumentsCandlesFactory,\n           \"DE30_EUR\",\n           {\"to\": \"2017-06-30T00:00:00Z\",\n            \"granularity\": \"M1\"},\n           {},\n           ValueError,\n        ),\n       (req.InstrumentsCandlesFactory,\n           \"EUR_GBP\",\n           {\"from\": \"2017-04-01T00:00:00Z\",\n            \"to\": \"2017-09-23T00:00:00Z\",\n            \"granularity\": \"M30\"},\n           {\"len\": 17},\n        ),\n       (req.InstrumentsCandlesFactory,\n           \"DE30_EUR\",\n           {\"from\": \"2017-01-01T00:00:00Z\",\n            \"to\": \"2017-06-30T00:00:00Z\",\n            \"granularity\": \"H4\"},\n           {\"len\": 3},\n        ),\n       (req.InstrumentsCandlesFactory,\n           \"DE30_EUR\",\n           {\"from\": \"2017-01-01T00:00:00Z\",\n            \"to\": \"2017-06-30T00:00:00Z\",\n            \"count\": 5000,         # same as previous, but increase batchsize\n            \"granularity\": \"H4\"},\n           {\"len\": 1},\n        ),\n    ])\n    def test__candlehistory(self, factory, instrument, inpar, refpar,\n                            exc=None):\n        \"\"\"candlehistoryfactory.\"\"\"\n        if not exc:\n            # run the factory\n            i = 0\n            for r in factory(instrument, params=inpar):\n                if i == 0 and inpar:\n                    self.assertTrue(r.params['from'] == inpar['from'])\n                    # the calculated 'to' should be there\n                    self.assertTrue('to' in r.params)\n                if 'len' in refpar and i == refpar['len']:\n                    self.assertTrue('to' not in r.params)\n                i += 1\n\n        # else:\n        #     with self.assertRaises(exc) as err:\n        #         r = factory(instrument, params=inpar)\n\n\nif __name__ == \"__main__\":\n\n    unittest.main()\n"
  },
  {
    "path": "tests/test_contrib_generic.py",
    "content": "import unittest\n\ntry:\n    from nose_parameterized import parameterized\nexcept ImportError:\n    print(\"*** Please install 'nose_parameterized' to run these tests ***\")\n    exit(0)\n\n\nimport oandapyV20.contrib.generic as gen\n\n\nclass TestContribGeneric(unittest.TestCase):\n    \"\"\"Tests regarding contrib generic.\"\"\"\n\n    def test__secs2time(self):\n        d = gen.secs2time(1497499200)\n        self.assertTrue(d.strftime(\"%Y%m%d-%H:%M:%S\") == '20170615-04:00:00')\n\n    @parameterized.expand([\n       (gen.granularity_to_time, \"M1\", 1*60),\n       (gen.granularity_to_time, \"M2\", 2*60),\n       (gen.granularity_to_time, \"M5\", 5*60),\n       (gen.granularity_to_time, \"M15\", 15*60),\n       (gen.granularity_to_time, \"H1\", 3600),\n       (gen.granularity_to_time, \"H4\", 4*3600),\n       (gen.granularity_to_time, \"D\", 86400),\n       (gen.granularity_to_time, \"D1\", 86400),\n       (gen.granularity_to_time, \"W\", 604800),\n       (gen.granularity_to_time, \"W1\", 604800),\n       (gen.granularity_to_time, \"K1\", 86400, ValueError),\n    ])\n    def test__granularity_to_time(self, meth, granularity, refval, exc=None):\n        \"\"\"granularity_to_time.\"\"\"\n        if not exc:\n            # run the factory\n            r = meth(granularity)\n            self.assertTrue(r == refval)\n\n        else:\n            with self.assertRaises(exc):\n                r = meth(granularity)\n\n\nif __name__ == \"__main__\":\n\n    unittest.main()\n"
  },
  {
    "path": "tests/test_contrib_orders.py",
    "content": "import unittest\n\ntry:\n    from nose_parameterized import parameterized\nexcept:\n    print(\"*** Please install 'nose_parameterized' to run these tests ***\")\n    exit(0)\n\n\nimport oandapyV20.contrib.requests as req\nimport oandapyV20.definitions.orders as OD\nimport oandapyV20.types as types\n\n\nclass TestContribRequests(unittest.TestCase):\n    \"\"\"Tests regarding contrib requests.\n\n    The reference is created using the second dict parameter. The\n    first dict parameter is merge with this, but only for the keys\n    that do NOT exist. That allows us to override parameters.\n    The result should reflect the data constructed by the class\n\n    \"\"\"\n\n    @parameterized.expand([\n       # MO\n       (req.MarketOrderRequest,\n           {\"instrument\": \"EUR_USD\",\n            \"units\": 10000},         # integer!\n           {'timeInForce': 'FOK',    # the default\n            'units': '10000',        # override, should be the str equiv.\n            'positionFill': 'DEFAULT',\n            'type': 'MARKET'}\n        ),\n       (req.MarketOrderRequest,\n           {\"instrument\": \"EUR_USD\",\n            \"priceBound\": 12345,     # integer\n            \"units\": \"10000\"},\n           {'timeInForce': 'FOK',\n            \"priceBound\": types.PriceValue(12345).value,\n            'positionFill': 'DEFAULT',\n            'type': 'MARKET'}\n        ),\n       (req.MarketOrderRequest,\n           {\"instrument\": \"EUR_USD\",\n            'timeInForce': 'GFD',     # should result in a ValueError\n            \"units\": \"10000\"},\n           {'positionFill': 'DEFAULT',\n            'type': 'MARKET'},\n           ValueError\n        ),\n       (req.MarketOrderRequest,\n           {\"instrument\": \"EUR_USD\",\n            'timeInForce': 'FOK',\n            'positionFill': 'WRONG',\n            \"units\": \"10000\"},\n           {'positionFill': 'WRONG',\n            'type': 'MARKET'},\n           ValueError\n        ),\n       # LO\n       (req.LimitOrderRequest,\n           {\"instrument\": \"EUR_USD\",\n            \"units\": 10000,     # integer\n            \"price\": 1.08},\n           {'timeInForce': 'GTC',\n            \"price\": '1.08000',\n            'positionFill': 'DEFAULT',\n            'type': 'LIMIT'\n            }\n        ),\n       (req.LimitOrderRequest,\n           {\"instrument\": \"EUR_USD\",\n            \"units\": \"10000\",    # string\n            \"price\": \"1.08\"},\n           {'timeInForce': 'GTC',\n            \"price\": '1.08000',\n            'positionFill': 'DEFAULT',\n            'type': 'LIMIT'\n            }\n        ),\n       # ... GTD, should raise a ValueError with missing date\n       (req.LimitOrderRequest,\n           {\"instrument\": \"EUR_USD\",\n            'timeInForce': 'GTD',\n            \"units\": 10000,\n            \"price\": 1.08},\n           {'timeInForce': 'GTD',\n            \"price\": '1.08000',\n            'positionFill': 'DEFAULT',\n            'type': 'LIMIT'},\n           ValueError\n        ),\n       # MIT\n       (req.MITOrderRequest,\n           {\"instrument\": \"EUR_USD\",\n            \"units\": 10000,\n            \"price\": 1.08},\n           {'timeInForce': 'GTC',\n            \"price\": '1.08000',\n            'positionFill': 'DEFAULT',\n            'type': 'MARKET_IF_TOUCHED'}\n        ),\n       # ... GTD, should raise a ValueError with missing date\n       (req.MITOrderRequest,\n           {\"instrument\": \"EUR_USD\",\n            'timeInForce': 'GTD',\n            \"units\": 10000,\n            \"price\": 1.08},\n           {'timeInForce': 'GTD',\n            \"price\": '1.08000',\n            'positionFill': 'DEFAULT',\n            'type': 'MARKET_IF_TOUCHED'},\n           ValueError\n        ),\n       # ... FOK, should raise a ValueError (not allowed)\n       (req.MITOrderRequest,\n           {\"instrument\": \"EUR_USD\",\n            'timeInForce': 'FOK',\n            \"units\": 10000,\n            \"price\": 1.08},\n           {'timeInForce': 'FOK',\n            \"price\": '1.08000',\n            'positionFill': 'DEFAULT',\n            'type': 'MARKET_IF_TOUCHED'},\n           ValueError\n        ),\n       # TPO\n       (req.TakeProfitOrderRequest,\n           {\"tradeID\": \"1234\",\n            \"price\": 1.22},\n           {'timeInForce': 'GTC',\n            \"price\": '1.22000',\n            'type': 'TAKE_PROFIT'}\n        ),\n       # ... GTD, should raise a ValueError with missing date\n       (req.TakeProfitOrderRequest,\n           {\"tradeID\": \"1234\",\n            \"timeInForce\": \"GTD\",\n            \"price\": 1.22},\n           {'timeInForce': 'GTD',\n            \"price\": '1.22000',\n            'type': 'TAKE_PROFIT'},\n           ValueError\n        ),\n       # ... FOK, should raise a ValueError (not allowed)\n       (req.TakeProfitOrderRequest,\n           {\"tradeID\": \"1234\",\n            \"timeInForce\": \"FOK\",\n            \"price\": 1.22},\n           {'timeInForce': 'FOK',\n            \"price\": '1.22000',\n            'type': 'TAKE_PROFIT'},\n           ValueError\n        ),\n       # SLO\n       (req.StopLossOrderRequest,\n           {\"tradeID\": \"1234\",\n            \"price\": 1.07},\n           {'timeInForce': 'GTC',\n            'type': 'STOP_LOSS',\n            'price': '1.07000'}\n        ),\n       # ... GTD, should raise a ValueError with missing date\n       (req.StopLossOrderRequest,\n           {\"tradeID\": \"1234\",\n            \"timeInForce\": \"GTD\",\n            \"price\": 1.07},\n           {'timeInForce': 'GTD',\n            'type': 'STOP_LOSS'},\n           ValueError\n        ),\n       # ... FOK, should raise a ValueError\n       (req.StopLossOrderRequest,\n           {\"tradeID\": \"1234\",\n            \"timeInForce\": \"FOK\",\n            \"price\": 1.07},\n           {'timeInForce': 'FOK',\n            'type': 'STOP_LOSS'},\n           ValueError\n        ),\n       # TSLO\n       (req.TrailingStopLossOrderRequest,\n           {\"tradeID\": \"1234\",\n            \"distance\": 20.5},\n           {'timeInForce': 'GTC',\n            \"distance\": '20.50000',\n            'type': 'TRAILING_STOP_LOSS'}\n        ),\n       # ... GTD, should raise a ValueError with missing date\n       (req.TrailingStopLossOrderRequest,\n           {\"tradeID\": \"1234\",\n            \"timeInForce\": \"GTD\",\n            \"distance\": 20.5},\n           {'timeInForce': 'GTD',\n            'type': 'TRAILING_STOP_LOSS'},\n           ValueError\n        ),\n       # ... FOK, should raise a ValueError (not allowed)\n       (req.TrailingStopLossOrderRequest,\n           {\"tradeID\": \"1234\",\n            \"timeInForce\": \"FOK\",\n            \"distance\": 20.5},\n           {'timeInForce': 'FOK',\n            \"distance\": \"20.50000\",\n            'type': 'TRAILING_STOP_LOSS'},\n           ValueError\n        ),\n       # SO\n       (req.StopOrderRequest,\n           {\"instrument\": \"EUR_USD\",\n            \"units\": 10000,\n            \"price\": 1.07},\n           {'timeInForce': 'GTC',\n            'positionFill': 'DEFAULT',\n            \"price\": \"1.07000\",\n            'type': 'STOP'}\n        ),\n       # ... GTD, should raise a ValueError with missing date\n       (req.StopOrderRequest,\n           {\"instrument\": \"EUR_USD\",\n            \"units\": 10000,\n            \"timeInForce\": \"GTD\",\n            \"price\": 1.07},\n           {'timeInForce': 'GTD',\n            'positionFill': 'DEFAULT',\n            \"price\": \"1.07000\",\n            'type': 'STOP'},\n           ValueError\n        ),\n    ])\n    def test__orders(self, cls, inpar, refpar, exc=None):\n        reference = dict({\"order\": refpar})\n\n        # update in reference all keys if they do not exists\n        for k in inpar.keys():\n            if k not in reference['order']:\n                reference['order'][k] = str(inpar[k])\n\n        if not exc:\n            r = cls(**inpar)\n            self.assertTrue(r.data == reference)\n        else:\n            with self.assertRaises(exc):\n                r = cls(**inpar)\n\n    @parameterized.expand([\n       # regular\n       (req.PositionCloseRequest,\n           {\"longUnits\": 10000,\n            \"shortUnits\": 2000},\n           {\"longUnits\": \"10000\",\n            \"shortUnits\": \"2000\"},\n        ),\n       # nothing\n       (req.PositionCloseRequest,\n           {},\n           {},\n           ValueError\n        ),\n       # client ext\n       (req.PositionCloseRequest,\n           {\"longUnits\": 10000,\n            \"shortUnits\": 2000,\n            \"longClientExtensions\": {\"key\": \"val\"}\n            },\n           {\"longUnits\": \"10000\",\n            \"shortUnits\": \"2000\",\n            \"longClientExtensions\": {\"key\": \"val\"}\n            },\n        ),\n       # client ext\n       (req.PositionCloseRequest,\n           {\"longUnits\": 10000,\n            \"shortUnits\": 2000,\n            \"shortClientExtensions\": {\"key\": \"val\"}\n            },\n           {\"longUnits\": \"10000\",\n            \"shortUnits\": \"2000\",\n            \"shortClientExtensions\": {\"key\": \"val\"}\n            },\n        ),\n       # regular\n       (req.TradeCloseRequest,\n           {\"units\": 10000},\n           {\"units\": \"10000\"}\n        ),\n       # default\n       (req.TradeCloseRequest,\n           {},\n           {\"units\": \"ALL\"}\n        ),\n       # TakeProfitDetails\n       (req.TakeProfitDetails,\n           {\"price\": 1.10},\n           {'timeInForce': 'GTC',\n            'price': '1.10000'}\n        ),\n       # .. raises ValueError because GTD required gtdTime\n       (req.TakeProfitDetails,\n           {\"price\": 1.10,\n            \"timeInForce\": OD.TimeInForce.GTD},\n           {'timeInForce': 'GTD',\n            'price': '1.10000'},\n           ValueError\n        ),\n       # .. raises ValueError because timeInForce must be GTC/GTD/GFD\n       (req.TakeProfitDetails,\n           {\"price\": 1.10,\n            \"timeInForce\": OD.TimeInForce.FOK},\n           {'timeInForce': 'FOK',\n            'price': '1.10000'},\n           ValueError\n        ),\n       # StopLossDetails\n       (req.StopLossDetails,\n           {\"price\": 1.10},\n           {'timeInForce': 'GTC',\n            'price': '1.10000'}\n        ),\n       # .. raises ValueError because GTD required gtdTime\n       (req.StopLossDetails,\n           {\"price\": 1.10,\n            \"timeInForce\": OD.TimeInForce.GTD},\n           {'timeInForce': 'GTD',\n            'price': '1.10000'},\n           ValueError\n        ),\n       # .. raises ValueError because timeInForce must be GTC/GTD/GFD\n       (req.StopLossDetails,\n           {\"price\": 1.10,\n            \"timeInForce\": OD.TimeInForce.FOK},\n           {'timeInForce': 'FOK',\n            'price': '1.10000'},\n           ValueError\n        ),\n       # TrailingStopLossDetails\n       (req.TrailingStopLossDetails,\n           {\"distance\": 25},\n           {'timeInForce': 'GTC',\n            'distance': '25.00000'}\n        ),\n       # .. raises ValueError because GTD required gtdTime\n       (req.TrailingStopLossDetails,\n           {\"distance\": 100,\n            \"timeInForce\": OD.TimeInForce.GTD},\n           {'timeInForce': 'GTD',\n            'distance': '100.00000'},\n           ValueError\n        ),\n       # .. raises ValueError because timeInForce must be GTC/GTD/GFD\n       (req.TrailingStopLossDetails,\n           {\"distance\": 100,\n            \"timeInForce\": OD.TimeInForce.FOK},\n           {'timeInForce': 'FOK',\n            'distance': '100.00000'},\n           ValueError\n        ),\n       # ClientExtensions\n       (req.ClientExtensions,\n           {\"clientID\": \"myID\"},\n           {\"id\": \"myID\"},\n        ),\n       (req.ClientExtensions,\n           {\"clientTag\": \"myTag\"},\n           {\"tag\": \"myTag\"},\n        ),\n       (req.ClientExtensions,\n           {\"clientComment\": \"myComment\"},\n           {\"comment\": \"myComment\"},\n        ),\n       # .. raises ValueError because no values were set\n       (req.ClientExtensions,\n           {},\n           {},\n           ValueError\n        ),\n    ])\n    def test__anonymous_body(self, cls, inpar, refpar, exc=None):\n\n        if not exc:\n            r = cls(**inpar) if inpar else cls()\n            self.assertTrue(r.data == refpar)\n        else:\n            with self.assertRaises(exc):\n                r = cls(**inpar)\n\n\nif __name__ == \"__main__\":\n\n    unittest.main()\n"
  },
  {
    "path": "tests/test_decorators.py",
    "content": "import unittest\nfrom oandapyV20.endpoints.decorators import extendargs, abstractclass\nfrom abc import ABCMeta, abstractmethod\nimport six\n\n\nclass TestDecorators(unittest.TestCase):\n    \"\"\"Tests decorators .\"\"\"\n\n    def test__extendargs(self):\n\n        class Something(object):\n            def __init__(self, x=10):\n                self.x = x\n\n        @extendargs(\"y\")\n        class SomethingExtra(Something):\n\n            def add(self):\n                return self.x + self.y\n\n        tst = SomethingExtra(x=10, y=20)\n        self.assertEqual(tst.add(), 30)\n\n    def test__abstractclass(self):\n\n        @six.add_metaclass(ABCMeta)\n        class Something(object):\n\n            @abstractmethod\n            def __init__(self, x=10):\n                self.x = x\n\n        @abstractclass\n        class SomethingElse(Something):\n            # derived classes from this class make use\n            # of this class __init__\n            # since this __init__ overrides the parent's\n            # @abstractmethod instances could be created,\n            # by making the class abstract with @abstractclass\n            # this can't be done, derived classes can\n            # ... that is the goal\n\n            def __init__(self, x=10, y=20):\n                super(SomethingElse, self).__init__(x)\n                self.y = y\n\n        class ABCDerived(SomethingElse):\n            pass\n\n        with self.assertRaises(TypeError):\n            Something(x=20)\n        with self.assertRaises(TypeError):\n            SomethingElse(x=20, y=30)\n\n        x = 20\n        y = 30\n        abcDerived = ABCDerived(x, y)\n        self.assertEqual(abcDerived.x + abcDerived.y, x+y)\n\n\nif __name__ == \"__main__\":\n\n    unittest.main()\n"
  },
  {
    "path": "tests/test_definitions.py",
    "content": "import unittest\n\nimport oandapyV20.definitions as allDEF\nfrom oandapyV20.definitions.orders import definitions as orderDefs\n\n\nclass TestDefinitions(unittest.TestCase):\n    \"\"\"Tests regarding the definitions.\"\"\"\n\n    def test__order_definitions(self):\n        \"\"\"test for the dynamically generated definition classes.\"\"\"\n        c = allDEF.orders.OrderType()\n        self.assertTrue(isinstance(c, allDEF.orders.OrderType) and\n                        c['MARKET'] == orderDefs['OrderType']['MARKET'])\n\n    def test__order_definitions_dictproperty(self):\n        \"\"\"test for the definitions property.\"\"\"\n        c = allDEF.orders.OrderType()\n        self.assertTrue(isinstance(c.definitions, dict) and\n                        c.definitions['MARKET'] == c['MARKET'])\n\n\nif __name__ == \"__main__\":\n\n    unittest.main()\n"
  },
  {
    "path": "tests/test_forexlabs.py",
    "content": "import sys\nimport unittest\nimport json\nfrom . import unittestsetup\nfrom .unittestsetup import environment as environment\nfrom .unittestsetup import TestData\nimport requests_mock\n\n\nfrom oandapyV20 import API\nimport oandapyV20.endpoints.forexlabs as labs\nfrom oandapyV20.endpoints.forexlabs import responses\n\naccess_token = None\naccountID = None\naccount_cur = None\napi = None\n\n\nclass TestForexLabs(unittest.TestCase):\n    \"\"\"Tests regarding the forexlabs endpoints.\"\"\"\n\n    def setUp(self):\n        \"\"\"setup for all tests.\"\"\"\n        global access_token\n        global accountID\n        global account_cur\n        global api\n        # self.maxDiff = None\n        try:\n            accountID, account_cur, access_token = unittestsetup.auth()\n            setattr(sys.modules[\"oandapyV20.oandapyV20\"],\n                    \"TRADING_ENVIRONMENTS\",\n                    {\"practice\": {\n                     \"stream\": \"https://test.com\",\n                     \"api\": \"https://test.com\",\n                     }})\n            api = API(environment=environment,\n                      access_token=access_token,\n                      headers={\"Content-Type\": \"application/json\"})\n            api.api_url = 'https://test.com'\n        except Exception as e:\n            print(\"%s\" % e)\n            exit(0)\n\n    @requests_mock.Mocker()\n    def test__calendar(self, mock_get):\n        \"\"\"get the calendar information for an instrument.\"\"\"\n        tid = \"_v3_forexlabs_calendar\"\n        td = TestData(responses, tid)\n        r = labs.Calendar(params=td.params)\n        mock_get.register_uri('GET',\n                              \"{}/{}\".format(api.api_url, r),\n                              text=json.dumps(td.resp))\n        api.request(r)\n        self.assertTrue(td.resp == r.response)\n\n    @requests_mock.Mocker()\n    def test__histposratios(self, mock_get):\n        \"\"\"get the hist. pos. ratios information for an instrument.\"\"\"\n        tid = \"_v3_forexlabs_histposratios\"\n        td = TestData(responses, tid)\n        r = labs.HistoricalPositionRatios(params=td.params)\n        mock_get.register_uri('GET',\n                              \"{}/{}\".format(api.api_url, r),\n                              text=json.dumps(td.resp))\n        api.request(r)\n        self.assertTrue(td.resp == r.response)\n\n    @requests_mock.Mocker()\n    def test__spreads(self, mock_get):\n        \"\"\"get the spreads information for an instrument.\"\"\"\n        tid = \"_v3_forexlabs_spreads\"\n        td = TestData(responses, tid)\n        r = labs.Spreads(params=td.params)\n        mock_get.register_uri('GET',\n                              \"{}/{}\".format(api.api_url, r),\n                              text=json.dumps(td.resp))\n        api.request(r)\n        self.assertTrue(td.resp == r.response)\n\n    @requests_mock.Mocker()\n    def test__commoftrad(self, mock_get):\n        \"\"\"get the commitments of traders information for an instrument.\"\"\"\n        tid = \"_v3_forexlabs_commoftrad\"\n        td = TestData(responses, tid)\n        r = labs.CommitmentsOfTraders(params=td.params)\n        mock_get.register_uri('GET',\n                              \"{}/{}\".format(api.api_url, r),\n                              text=json.dumps(td.resp))\n        api.request(r)\n        self.assertTrue(td.resp == r.response)\n\n    @requests_mock.Mocker()\n    def test__orderbookdata(self, mock_get):\n        \"\"\"get the orderbookdata information for an instrument.\"\"\"\n        tid = \"_v3_forexlabs_orderbookdata\"\n        td = TestData(responses, tid)\n        r = labs.OrderbookData(params=td.params)\n        mock_get.register_uri('GET',\n                              \"{}/{}\".format(api.api_url, r),\n                              text=json.dumps(td.resp))\n        api.request(r)\n        self.assertTrue(td.resp == r.response)\n\n    @requests_mock.Mocker()\n    def test__autochartist(self, mock_get):\n        \"\"\"get autochartist information for an instrument.\"\"\"\n        tid = \"_v3_forexlabs_autochartist\"\n        td = TestData(responses, tid)\n        r = labs.Autochartist(params=td.params)\n        mock_get.register_uri('GET',\n                              \"{}/{}\".format(api.api_url, r),\n                              text=json.dumps(td.resp))\n        api.request(r)\n        self.assertTrue(td.resp == r.response)\n"
  },
  {
    "path": "tests/test_instruments.py",
    "content": "import sys\nimport unittest\nimport json\nfrom . import unittestsetup\nfrom .unittestsetup import environment as environment\nfrom .unittestsetup import fetchTestData\nimport requests_mock\n\n\nfrom oandapyV20 import API\nfrom oandapyV20.endpoints.instruments import responses\nimport oandapyV20.endpoints.instruments as instruments\n\naccess_token = None\naccountID = None\naccount_cur = None\napi = None\n\n\nclass TestInstruments(unittest.TestCase):\n    \"\"\"Tests regarding the instruments endpoints.\"\"\"\n\n    def setUp(self):\n        \"\"\"setup for all tests.\"\"\"\n        global access_token\n        global accountID\n        global account_cur\n        global api\n        # self.maxDiff = None\n        try:\n            accountID, account_cur, access_token = unittestsetup.auth()\n            setattr(sys.modules[\"oandapyV20.oandapyV20\"],\n                    \"TRADING_ENVIRONMENTS\",\n                    {\"practice\": {\n                     \"stream\": \"https://test.com\",\n                     \"api\": \"https://test.com\",\n                     }})\n            api = API(environment=environment,\n                      access_token=access_token,\n                      headers={\"Content-Type\": \"application/json\"})\n            api.api_url = \"https://test.com\"\n        except Exception as e:\n            print(\"%s\" % e)\n            exit(0)\n\n    @requests_mock.Mocker()\n    def test__instruments_candles(self, mock_get):\n        \"\"\"get the candle information for instruments.\"\"\"\n        instrument = \"DE30_EUR\"\n        tid = \"_v3_instruments_instrument_candles\"\n        resp, data, params = fetchTestData(responses, tid)\n        r = instruments.InstrumentsCandles(instrument=instrument,\n                                           params=params)\n        mock_get.register_uri('GET',\n                              \"{}/{}\".format(api.api_url, r),\n                              text=json.dumps(resp))\n        result = api.request(r)\n        self.assertTrue(result == resp)\n\n    @requests_mock.Mocker()\n    def test__instruments_orderbook(self, mock_get):\n        \"\"\"get the orderbook information for instruments.\"\"\"\n        instrument = \"EUR_USD\"\n        tid = \"_v3_instruments_instrument_orderbook\"\n        resp, data, params = fetchTestData(responses, tid)\n        r = instruments.InstrumentsOrderBook(instrument=instrument,\n                                             params=params)\n        mock_get.register_uri('GET',\n                              \"{}/{}\".format(api.api_url, r),\n                              text=json.dumps(resp))\n        result = api.request(r)\n        self.assertTrue(result == resp)\n\n    @requests_mock.Mocker()\n    def test__instruments_positionbook(self, mock_get):\n        \"\"\"get the positionbook information for instruments.\"\"\"\n        instrument = \"EUR_USD\"\n        tid = \"_v3_instruments_instrument_positionbook\"\n        resp, data, params = fetchTestData(responses, tid)\n        r = instruments.InstrumentsPositionBook(instrument=instrument,\n                                                params=params)\n        mock_get.register_uri('GET',\n                              \"{}/{}\".format(api.api_url, r),\n                              text=json.dumps(resp))\n        result = api.request(r)\n        self.assertTrue(result == resp)\n\n\nif __name__ == \"__main__\":\n\n    unittest.main()\n"
  },
  {
    "path": "tests/test_oandapyv20.py",
    "content": "import sys\nimport unittest\nfrom . import unittestsetup\nfrom .unittestsetup import environment as environment\nfrom oandapyV20 import API\n\naccess_token = None\naccountID = None\naccount_cur = None\napi = None\n\n\nclass TestOandapyV20(unittest.TestCase):\n    \"\"\"Tests regarding the client.\"\"\"\n\n    def setUp(self):\n        \"\"\"setup for all tests.\"\"\"\n        global access_token\n        global accountID\n        global account_cur\n        global api\n        # self.maxDiff = None\n        try:\n            accountID, account_cur, access_token = unittestsetup.auth()\n            setattr(sys.modules[\"oandapyV20.oandapyV20\"],\n                    \"TRADING_ENVIRONMENTS\",\n                    {\"practice\": {\n                     \"stream\": \"https://test.com\",\n                     \"api\": \"https://test.com\",\n                     }})\n            api = API(environment=environment,\n                      access_token=access_token,\n                      headers={\"Content-Type\": \"application/json\"})\n        except Exception as e:\n            print(\"%s\" % e)\n            exit(0)\n\n    def test__oandapyv20_environment(self):\n        \"\"\"test the exception on a faulty environment.\"\"\"\n        with self.assertRaises(KeyError) as envErr:\n            API(environment=\"faulty\",\n                access_token=access_token,\n                headers={\"Content-Type\": \"application/json\"})\n\n        self.assertTrue(\"Unknown environment\" in \"{}\".format(envErr.exception))\n\n    def test__requests_params(self):\n        \"\"\"request parameters.\"\"\"\n        request_params = {\"timeout\": 10}\n        api = API(environment=environment,\n                  access_token=access_token,\n                  headers={\"Content-Type\": \"application/json\"},\n                  request_params=request_params)\n        self.assertTrue(api.request_params == request_params)\n\n    def test__requests_exception(self):\n        \"\"\"force a requests exception.\"\"\"\n        from requests.exceptions import RequestException\n        import oandapyV20.endpoints.accounts as accounts\n        setattr(sys.modules[\"oandapyV20.oandapyV20\"],\n                \"TRADING_ENVIRONMENTS\",\n                {\"practice\": {\n                 \"stream\": \"ttps://test.com\",\n                 \"api\": \"ttps://test.com\",\n                 }})\n        api = API(environment=environment,\n                  access_token=access_token,\n                  headers={\"Content-Type\": \"application/json\"})\n        text = \"No connection \" \\\n               \"adapters were found for 'ttps://test.com/v3/accounts'\"\n        r = accounts.AccountList()\n        with self.assertRaises(RequestException) as oErr:\n            api.request(r)\n\n        self.assertEqual(\"{}\".format(oErr.exception), text)\n\n\nif __name__ == \"__main__\":\n\n    unittest.main()\n"
  },
  {
    "path": "tests/test_orders.py",
    "content": "import sys\nimport unittest\nimport json\nfrom . import unittestsetup\nfrom .unittestsetup import environment as environment\nfrom .unittestsetup import fetchTestData\nimport requests_mock\n\n\nfrom oandapyV20 import API\nimport oandapyV20.endpoints.orders as orders\nfrom oandapyV20.endpoints.orders import responses\n\naccess_token = None\naccountID = None\naccount_cur = None\napi = None\n\n\nclass TestOrders(unittest.TestCase):\n    \"\"\"Tests regarding the orders endpoints.\"\"\"\n\n    def setUp(self):\n        \"\"\"setup for all tests.\"\"\"\n        global access_token\n        global accountID\n        global account_cur\n        global api\n        # self.maxDiff = None\n        try:\n            accountID, account_cur, access_token = unittestsetup.auth()\n            setattr(sys.modules[\"oandapyV20.oandapyV20\"],\n                    \"TRADING_ENVIRONMENTS\",\n                    {\"practice\": {\n                     \"stream\": \"https://test.com\",\n                     \"api\": \"https://test.com\",\n                     }})\n            api = API(environment=environment,\n                      access_token=access_token,\n                      headers={\"Content-Type\": \"application/json\"})\n            api.api_url = 'https://test.com'\n        except Exception as e:\n            print(\"%s\" % e)\n            exit(0)\n\n    def test__orders_base_exception(self):\n        \"\"\"test for the exception when using the baseclass.\"\"\"\n        with self.assertRaises(TypeError) as bcErr:\n            orders.Orders(accountID)\n\n        bcErr = bcErr.exception\n        print(\"FOUTJE: \", str(bcErr))\n        self.assertTrue(\"Can't instantiate abstract class Orders \"\n                        \"with abstract method\" in \"{}\".format(bcErr))\n\n    @requests_mock.Mocker()\n    def test__order_create(self, mock_post):\n        \"\"\"order create.\"\"\"\n        tid = \"_v3_accounts_accountID_orders_create\"\n        resp, data = fetchTestData(responses, tid)\n        r = orders.OrderCreate(accountID, data=data)\n        mock_post.register_uri('POST',\n                               \"{}/{}\".format(api.api_url, r),\n                               text=json.dumps(resp),\n                               status_code=r.expected_status)\n        result = api.request(r)\n        self.assertTrue(result == resp)\n\n    @requests_mock.Mocker()\n    def test__order_clientextensions(self, mock_put):\n        \"\"\"set order client extensions.\"\"\"\n        tid = \"_v3_accounts_accountID_order_clientextensions\"\n        resp, data = fetchTestData(responses, tid)\n        r = orders.OrderClientExtensions(accountID, orderID=\"2304\", data=data)\n        mock_put.register_uri('PUT',\n                              \"{}/{}\".format(api.api_url, r),\n                              text=json.dumps(resp),\n                              status_code=r.expected_status)\n        result = api.request(r)\n        self.assertTrue(result == resp)\n\n    @requests_mock.Mocker()\n    def test__orders_pending(self, mock_get):\n        \"\"\"get the orders pending for an account.\"\"\"\n        tid = \"_v3_accounts_accountID_orders_pending\"\n        resp, data = fetchTestData(responses, tid)\n        r = orders.OrdersPending(accountID)\n        mock_get.register_uri('GET',\n                              \"{}/{}\".format(api.api_url, r),\n                              text=json.dumps(resp),\n                              status_code=r.expected_status)\n        result = api.request(r)\n        self.assertTrue(result == resp)\n\n    @requests_mock.Mocker()\n    def test__orders_list(self, mock_get):\n        \"\"\"get the orders for an account.\"\"\"\n        tid = \"_v3_accounts_accountID_orders_list\"\n        resp, data = fetchTestData(responses, tid)\n        r = orders.OrderList(accountID)\n        mock_get.register_uri('GET',\n                              \"{}/{}\".format(api.api_url, r),\n                              text=json.dumps(resp))\n        result = api.request(r)\n        self.assertTrue(\n            len(result['orders']) == len(resp['orders']) and\n            result['orders'][0]['instrument'] ==\n            resp['orders'][0]['instrument'])\n\n    @requests_mock.Mocker()\n    def test__order_details(self, mock_get):\n        \"\"\"details of an order.\"\"\"\n        orderID = \"2309\"\n        tid = \"_v3_accounts_accountID_order_details\"\n        resp, data = fetchTestData(responses, tid)\n        r = orders.OrderDetails(accountID, orderID=orderID)\n        mock_get.register_uri('GET',\n                              \"{}/{}\".format(api.api_url, r),\n                              text=json.dumps(resp))\n        result = api.request(r)\n        result = result[\"order\"]\n        self.assertTrue(result['id'] == orderID and\n                        result['units'] == resp[\"order\"][\"units\"])\n\n    @requests_mock.Mocker()\n    def test__order_cancel(self, mock_get):\n        \"\"\"cancel an order.\"\"\"\n        orderID = \"2307\"\n        tid = \"_v3_accounts_accountID_order_cancel\"\n        resp, data = fetchTestData(responses, tid)\n        r = orders.OrderCancel(accountID, orderID=orderID)\n        mock_get.register_uri('PUT',\n                              \"{}/{}\".format(api.api_url, r),\n                              text=json.dumps(resp))\n        result = api.request(r)\n        result = result[\"orderCancelTransaction\"]\n        self.assertTrue(result['orderID'] == orderID and\n                        result['reason'] == \"CLIENT_REQUEST\" and\n                        result['type'] == \"ORDER_CANCEL\")\n\n    @requests_mock.Mocker()\n    def test__order_replace(self, mock_put):\n        \"\"\"replace an order.\"\"\"\n        orderID = \"2304\"\n        # to replace with data\n        tid = \"_v3_accounts_accountID_order_replace\"\n        resp, data = fetchTestData(responses, tid)\n        r = orders.OrderReplace(accountID, orderID, data=data)\n        mock_put.register_uri('PUT',\n                              \"{}/{}\".format(api.api_url, r),\n                              text=json.dumps(resp),\n                              status_code=r.expected_status)\n        result = api.request(r)\n        self.assertTrue(\n          \"orderCreateTransaction\" in result and\n          \"orderCancelTransaction\" in result and\n          result[\"orderCancelTransaction\"][\"orderID\"] == orderID and\n          result[\"orderCreateTransaction\"][\"replacesOrderID\"] == orderID and\n          result[\"orderCreateTransaction\"][\"units\"] ==\n          data[\"order\"]['units'] and\n          result[\"orderCreateTransaction\"][\"price\"] ==\n          data[\"order\"]['price'])\n\n    @requests_mock.Mocker()\n    def test__order_replace_wrong_status_exception(self, mock_get):\n        \"\"\"replacing an order with success but wrong status_code.\"\"\"\n        orderID = \"2125\"\n        # to replace with\n        tmp = {\"order\": {\n                   \"units\": \"-50000\",\n                   \"type\": \"LIMIT\",\n                   \"instrument\": \"EUR_USD\",\n                   \"price\": \"1.25\",\n                }\n               }\n\n        uri = 'https://test.com/v3/accounts/{}/orders/{}'.format(accountID,\n                                                                 orderID)\n        resp = responses[\"_v3_accounts_accountID_order_replace\"]['response']\n        text = json.dumps(resp)\n        r = orders.OrderReplace(accountID, orderID, data=tmp)\n        # force the wrong status code\n        mock_get.register_uri('PUT',\n                              uri,\n                              text=text,\n                              status_code=200)\n        with self.assertRaises(ValueError) as err:\n            api.request(r)\n\n        self.assertTrue(\"200\" in \"{}\".format(err.exception) and\n                        r.status_code is None)\n\nif __name__ == \"__main__\":\n\n    unittest.main()\n"
  },
  {
    "path": "tests/test_positions.py",
    "content": "import sys\nimport unittest\nimport json\nfrom . import unittestsetup\nfrom .unittestsetup import environment as environment\nfrom .unittestsetup import fetchTestData\nimport requests_mock\n\n\nfrom oandapyV20 import API\nimport oandapyV20.endpoints.positions as positions\nfrom oandapyV20.endpoints.positions import responses\n\naccess_token = None\naccountID = None\naccount_cur = None\napi = None\n\n\nclass TestPositions(unittest.TestCase):\n    \"\"\"Tests regarding the positions endpoints.\"\"\"\n\n    def setUp(self):\n        \"\"\"setup for all tests.\"\"\"\n        global access_token\n        global accountID\n        global account_cur\n        global api\n        # self.maxDiff = None\n        try:\n            accountID, account_cur, access_token = unittestsetup.auth()\n            setattr(sys.modules[\"oandapyV20.oandapyV20\"],\n                    \"TRADING_ENVIRONMENTS\",\n                    {\"practice\": {\n                     \"stream\": \"https://test.com\",\n                     \"api\": \"https://test.com\",\n                     }})\n            api = API(environment=environment,\n                      access_token=access_token)\n            api.api_url = 'https://test.com'\n        except Exception as e:\n            print(\"%s\" % e)\n            exit(0)\n\n    @requests_mock.Mocker()\n    def test__positions_list(self, mock_get):\n        \"\"\"get the positions list for an account.\"\"\"\n        tid = \"_v3_accounts_accountID_positions\"\n        resp, data = fetchTestData(responses, tid)\n        r = positions.PositionList(accountID)\n        mock_get.register_uri('GET',\n                              \"{}/{}\".format(api.api_url, r),\n                              text=json.dumps(resp))\n        result = api.request(r)\n        self.assertTrue(resp == result)\n\n    @requests_mock.Mocker()\n    def test__openpositions_list(self, mock_get):\n        \"\"\"get the openpositions list for an account.\"\"\"\n        tid = \"_v3_accounts_accountID_openpositions\"\n        resp, data = fetchTestData(responses, tid)\n        r = positions.OpenPositions(accountID)\n        mock_get.register_uri('GET',\n                              \"{}/{}\".format(api.api_url, r),\n                              text=json.dumps(resp))\n        result = api.request(r)\n        self.assertTrue(resp == result)\n\n    @requests_mock.Mocker()\n    def test__positiondetails(self, mock_get):\n        \"\"\"get the details of a single instrument's position.\"\"\"\n        tid = \"_v3_accounts_accountID_positiondetails\"\n        resp, data = fetchTestData(responses, tid)\n        r = positions.PositionDetails(accountID, instrument=\"EUR_USD\")\n        mock_get.register_uri('GET',\n                              \"{}/{}\".format(api.api_url, r),\n                              text=json.dumps(resp))\n        result = api.request(r)\n        self.assertTrue(resp == result)\n\n    @requests_mock.Mocker()\n    def test__positionclose(self, mock_put):\n        \"\"\"close single instrument's position long side.\"\"\"\n        tid = \"_v3_accounts_accountID_position_close\"\n        resp, data = fetchTestData(responses, tid)\n        r = positions.PositionClose(accountID, instrument=\"EUR_USD\", data=data)\n        mock_put.register_uri('PUT',\n                              \"{}/{}\".format(api.api_url, r),\n                              text=json.dumps(resp))\n        result = api.request(r)\n        self.assertTrue(resp == result)\n\n\nif __name__ == \"__main__\":\n\n    unittest.main()\n"
  },
  {
    "path": "tests/test_pricing.py",
    "content": "import sys\nimport unittest\nimport json\nfrom . import unittestsetup\nfrom .unittestsetup import environment as environment\nfrom .unittestsetup import fetchTestData\nimport requests_mock\n\n\nfrom oandapyV20 import API\nfrom oandapyV20.exceptions import StreamTerminated\nimport oandapyV20.endpoints.pricing as pricing\nfrom oandapyV20.endpoints.pricing import responses\n\naccess_token = None\naccountID = None\naccount_cur = None\napi = None\n\n\nclass TestPricing(unittest.TestCase):\n    \"\"\"Tests regarding the pricing endpoints.\"\"\"\n\n    def setUp(self):\n        \"\"\"setup for all tests.\"\"\"\n        global access_token\n        global accountID\n        global account_cur\n        global api\n        # self.maxDiff = None\n        try:\n            accountID, account_cur, access_token = unittestsetup.auth()\n            setattr(sys.modules[\"oandapyV20.oandapyV20\"],\n                    \"TRADING_ENVIRONMENTS\",\n                    {\"practice\": {\n                     \"stream\": \"https://test.com\",\n                     \"api\": \"https://test.com\",\n                     }})\n            api = API(environment=environment,\n                      access_token=access_token)\n            api.api_url = 'https://test.com'\n        except Exception as e:\n            print(\"%s\" % e)\n            exit(0)\n\n    @requests_mock.Mocker()\n    def test__pricing(self, mock_get):\n        \"\"\"get the pricing information for instruments.\"\"\"\n        tid = \"_v3_accounts_accountID_pricing\"\n        resp, data, params = fetchTestData(responses, tid)\n        r = pricing.PricingInfo(accountID, params=params)\n        mock_get.register_uri('GET',\n                              \"{}/{}\".format(api.api_url, r),\n                              text=json.dumps(resp))\n        result = api.request(r)\n        instr = params[\"instruments\"].split(\",\")\n        self.assertTrue(result[\"prices\"][0][\"instrument\"] == instr[0] and\n                        result[\"prices\"][1][\"instrument\"] == instr[1])\n\n    @requests_mock.Mocker()\n    def test__pricing_stream(self, mock_get):\n        \"\"\"get the streaming pricing information for instruments.\"\"\"\n        tid = \"_v3_accounts_accountID_pricing_stream\"\n        resp, data, params = fetchTestData(responses, tid)\n        text = \"\\n\".join([json.dumps(t) for t in resp])\n        r = pricing.PricingStream(accountID, params=params)\n        mock_get.register_uri('GET',\n                              \"{}/{}\".format(api.api_url, r),\n                              text=text)\n        result = []\n        n = 0\n        m = 3\n        with self.assertRaises(StreamTerminated):\n            for rec in api.request(r):\n                result.append(rec)\n                n += 1\n                # terminate when we have m response lines\n                if n == m:\n                    r.terminate()\n\n        # the result containing m items, should equal the first m items\n        self.assertTrue(result == resp[0:m])\n\n    def test__pricing_stream_termination_1(self):\n        \"\"\"terminate a stream that does not exist.\"\"\"\n        params = {\"instruments\": \"EUR_USD,EUR_JPY\"}\n        r = pricing.PricingStream(accountID, params=params)\n        with self.assertRaises(ValueError):\n            r.terminate()\n\nif __name__ == \"__main__\":\n\n    unittest.main()\n"
  },
  {
    "path": "tests/test_trades.py",
    "content": "import sys\nimport unittest\nimport json\nfrom . import unittestsetup\nfrom .unittestsetup import environment as environment\nfrom .unittestsetup import fetchTestData\nimport requests_mock\n\n\nfrom oandapyV20 import API\nimport oandapyV20.endpoints.trades as trades\nfrom oandapyV20.endpoints.trades import responses\n\naccess_token = None\naccountID = None\naccount_cur = None\napi = None\n\n\nclass TestTrades(unittest.TestCase):\n    \"\"\"Tests regarding the trades endpoints.\"\"\"\n\n    def setUp(self):\n        \"\"\"setup for all tests.\"\"\"\n        global access_token\n        global accountID\n        global account_cur\n        global api\n        # self.maxDiff = None\n        try:\n            accountID, account_cur, access_token = unittestsetup.auth()\n            setattr(sys.modules[\"oandapyV20.oandapyV20\"],\n                    \"TRADING_ENVIRONMENTS\",\n                    {\"practice\": {\n                     \"stream\": \"https://test.com\",\n                     \"api\": \"https://test.com\",\n                     }})\n            api = API(environment=environment, access_token=access_token)\n            api.api_url = 'https://test.com'\n        except Exception as e:\n            print(\"%s\" % e)\n            exit(0)\n\n    @requests_mock.Mocker()\n    def test__trades_list(self, mock_get):\n        \"\"\"get the trades information for an account.\"\"\"\n        tid = \"_v3_accounts_accountID_trades\"\n        resp, data, params = fetchTestData(responses, tid)\n        r = trades.TradesList(accountID, params=params)\n        mock_get.register_uri('GET',\n                              \"{}/{}\".format(api.api_url, r),\n                              text=json.dumps(resp))\n        result = api.request(r)\n        self.assertTrue(result == resp)\n\n    @requests_mock.Mocker()\n    def test__open_trades(self, mock_get):\n        \"\"\"get the open trades information for an account.\"\"\"\n        tid = \"_v3_accounts_accountID_opentrades\"\n        resp, data = fetchTestData(responses, tid)\n        r = trades.OpenTrades(accountID)\n        mock_get.register_uri('GET',\n                              \"{}/{}\".format(api.api_url, r),\n                              text=json.dumps(resp))\n        result = api.request(r)\n        self.assertTrue(result == resp)\n\n    @requests_mock.Mocker()\n    def test__trade_details(self, mock_get):\n        \"\"\"get the trade details for a trade.\"\"\"\n        tid = \"_v3_account_accountID_trades_details\"\n        resp, data = fetchTestData(responses, tid)\n        r = trades.TradeDetails(accountID, tradeID=2315)\n        mock_get.register_uri('GET',\n                              \"{}/{}\".format(api.api_url, r),\n                              text=json.dumps(resp))\n        result = api.request(r)\n        self.assertTrue(result == resp)\n\n    @requests_mock.Mocker()\n    def test__trade_close(self, mock_put):\n        \"\"\"close trade by id .\"\"\"\n        tid = \"_v3_account_accountID_trades_close\"\n        resp, data = fetchTestData(responses, tid)\n        r = trades.TradeClose(accountID, tradeID=2315)\n        mock_put.register_uri('PUT',\n                              \"{}/{}\".format(api.api_url, r),\n                              text=json.dumps(resp))\n        result = api.request(r)\n        self.assertTrue(result == resp)\n\n    @requests_mock.Mocker()\n    def test__trade_cltext(self, mock_put):\n        \"\"\"trade client extensions.\"\"\"\n        tid = \"_v3_account_accountID_trades_cltext\"\n        resp, data = fetchTestData(responses, tid)\n        r = trades.TradeClientExtensions(accountID, tradeID=2315, data=data)\n        mock_put.register_uri('PUT',\n                              \"{}/{}\".format(api.api_url, r),\n                              text=json.dumps(resp))\n        result = api.request(r)\n        self.assertTrue(result == resp)\n\n    @requests_mock.Mocker()\n    def test__trade_crcdo(self, mock_put):\n        \"\"\"trade client extensions.\"\"\"\n        tid = \"_v3_account_accountID_trades_crcdo\"\n        resp, data = fetchTestData(responses, tid)\n        r = trades.TradeCRCDO(accountID, tradeID=2323, data=data)\n        mock_put.register_uri('PUT',\n                              \"{}/{}\".format(api.api_url, r),\n                              text=json.dumps(resp))\n        result = api.request(r)\n        self.assertTrue(result == resp)\n\n    @requests_mock.Mocker()\n    def test__trades_list_byids(self, mock_get):\n        \"\"\"get the trades information for an account.\"\"\"\n        uri = 'https://test.com/v3/accounts/{}/trades'.format(accountID)\n        resp = responses[\"_v3_accounts_accountID_trades\"]['response']\n        text = json.dumps(resp)\n        mock_get.register_uri('GET',\n                              uri,\n                              text=text)\n        params = {\"ids\": \"2121, 2123\"}\n        r = trades.TradesList(accountID, params=params)\n        result = api.request(r)\n        self.assertTrue(len(result['trades']) == 2 and\n                        result['trades'][0]['instrument'] == \"DE30_EUR\")\n\n\nif __name__ == \"__main__\":\n\n    unittest.main()\n"
  },
  {
    "path": "tests/test_transactions.py",
    "content": "import sys\nimport unittest\nimport json\nfrom . import unittestsetup\nfrom .unittestsetup import environment as environment\nfrom .unittestsetup import fetchTestData\nimport requests_mock\n\n\nfrom oandapyV20 import API\nfrom oandapyV20.exceptions import StreamTerminated\nimport oandapyV20.endpoints.transactions as transactions\nfrom oandapyV20.endpoints.transactions import responses\n\naccess_token = None\naccountID = None\naccount_cur = None\napi = None\n\n\nclass TestTransactions(unittest.TestCase):\n    \"\"\"Tests regarding the transactions endpoints.\"\"\"\n\n    def setUp(self):\n        \"\"\"setup for all tests.\"\"\"\n        global access_token\n        global accountID\n        global account_cur\n        global api\n        # self.maxDiff = None\n        try:\n            accountID, account_cur, access_token = unittestsetup.auth()\n            setattr(sys.modules[\"oandapyV20.oandapyV20\"],\n                    \"TRADING_ENVIRONMENTS\",\n                    {\"practice\": {\n                     \"stream\": \"https://test.com\",\n                     \"api\": \"https://test.com\",\n                     }})\n            api = API(environment=environment,\n                      access_token=access_token,\n                      headers={\"Content-Type\": \"application/json\"})\n            api.api_url = 'https://test.com'\n        except Exception as e:\n            print(\"%s\" % e)\n            exit(0)\n\n    @requests_mock.Mocker()\n    def test__transactions(self, mock_get):\n        \"\"\"get the transactions information for an account.\"\"\"\n        tid = \"_v3_accounts_accountID_transactions\"\n        resp, data, params = fetchTestData(responses, tid)\n        r = transactions.TransactionList(accountID)\n        mock_get.register_uri('GET',\n                              \"{}/{}\".format(api.api_url, r),\n                              text=json.dumps(resp))\n        api.request(r)\n        self.assertTrue(resp == r.response)\n\n    @requests_mock.Mocker()\n    def test__transactions_details(self, mock_get):\n        \"\"\"get the transactions details for a transaction.\"\"\"\n        tid = \"_v3_accounts_transaction_details\"\n        resp, data = fetchTestData(responses, tid)\n        transactionID = 2304\n        r = transactions.TransactionDetails(accountID, transactionID)\n        mock_get.register_uri('GET',\n                              \"{}/{}\".format(api.api_url, r),\n                              text=json.dumps(resp))\n        api.request(r)\n        self.assertTrue(resp == r.response)\n\n    @requests_mock.Mocker()\n    def test__transactions_idrange(self, mock_get):\n        \"\"\"get the transactions by an idrange.\"\"\"\n        tid = \"_v3_accounts_transaction_idrange\"\n        resp, data, params = fetchTestData(responses, tid)\n        r = transactions.TransactionIDRange(accountID, params=params)\n        mock_get.register_uri('GET',\n                              \"{}/{}\".format(api.api_url, r),\n                              text=json.dumps(resp))\n        api.request(r)\n        self.assertTrue(resp == r.response)\n\n    @requests_mock.Mocker()\n    def test__transactions_sinceid(self, mock_get):\n        \"\"\"get the transactions since an id.\"\"\"\n        tid = \"_v3_accounts_transaction_sinceid\"\n        resp, data, params = fetchTestData(responses, tid)\n        r = transactions.TransactionsSinceID(accountID, params=params)\n        mock_get.register_uri('GET',\n                              \"{}/{}\".format(api.api_url, r),\n                              text=json.dumps(resp))\n        api.request(r)\n        self.assertTrue(resp == r.response)\n\n    @requests_mock.Mocker()\n    def test__transaction_stream(self, mock_get):\n        \"\"\"get the streaming transaction information.\"\"\"\n        tid = \"_v3_accounts_transactions_stream\"\n        resp, data = fetchTestData(responses, tid)\n        text = \"\\n\".join([json.dumps(t) for t in resp])\n        r = transactions.TransactionsStream(accountID)\n        mock_get.register_uri('GET',\n                              \"{}/{}\".format(api.api_url, r),\n                              text=text)\n        result = []\n        n = 0\n        m = 5\n        with self.assertRaises(StreamTerminated):\n            api.request(r)\n            for rv in r.response:\n                result.append(rv)\n                n += 1\n                # terminate when we have 3 response lines\n                if n == m:\n                    r.terminate()\n\n        # the result containing m items, should equal the first m items\n        # of the source\n        self.assertTrue(result == resp[0:m])\n\n    def test__transaction_stream_termination_1(self):\n        \"\"\"terminate a stream that does not exist.\"\"\"\n        r = transactions.TransactionsStream(accountID)\n        with self.assertRaises(ValueError):\n            r.terminate()\n\nif __name__ == \"__main__\":\n\n    unittest.main()\n"
  },
  {
    "path": "tests/test_types.py",
    "content": "import unittest\nfrom datetime import datetime\n\ntry:\n    from nose_parameterized import parameterized\nexcept:\n    print(\"*** Please install 'nose_parameterized' to run these tests ***\")\n    exit(0)\n\n\nimport oandapyV20.types as tp\n\nNOW = datetime.now()\n\n\nclass TestTypes(unittest.TestCase):\n    \"\"\"Tests types.\"\"\"\n\n    @parameterized.expand([\n       # AccountID\n       (tp.AccountID,\n           {\"accountID\": \"001-011-5838423-001\"},\n           {\"siteID\": \"001\",\n            \"divisionID\": \"011\",\n            \"userID\": \"5838423\",\n            \"accountNumber\": \"001\"}\n        ),\n       (tp.AccountID,\n           {\"accountID\": \"0010115838423001\"},\n           {\"siteID\": \"001\",\n            \"divisionID\": \"011\",\n            \"userID\": \"5838423\",\n            \"accountNumber\": \"001\"},\n        ValueError\n        ),\n       # OrderID\n       (tp.OrderID,\n           {\"orderID\": \"1234\"},\n           \"1234\",\n        ),\n       (tp.OrderID,\n           {\"orderID\": 1234},\n           \"1234\",\n        ),\n       (tp.OrderID,\n           {\"orderID\": -1234},\n           \"1234\",\n        ValueError\n        ),\n       # TradeID\n       (tp.TradeID,\n           {\"tradeID\": \"1234\"},\n           \"1234\",\n        ),\n       (tp.TradeID,\n           {\"tradeID\": 1234},\n           \"1234\",\n        ),\n       (tp.TradeID,\n           {\"tradeID\": -1234},\n           \"1234\",\n        ValueError\n        ),\n       # AccountUnits\n       (tp.AccountUnits,\n           {\"units\": 1234},\n           \"1234.00000\",\n        ),\n       (tp.AccountUnits,\n           {\"units\": \"1234\"},\n           \"1234.00000\",\n        ),\n       # PriceValue\n       (tp.PriceValue,\n           {\"priceValue\": 1234},\n           \"1234.00000\",\n        ),\n       (tp.PriceValue,\n           {\"priceValue\": \"1234\"},\n           \"1234.00000\",\n        ),\n       # Units\n       (tp.Units,\n           {\"units\": 1234},\n           \"1234\",\n        ),\n       (tp.Units,\n           {\"units\": \"-1234\"},\n           \"-1234\",\n        ),\n       (tp.Units,\n           {\"units\": 10.5},\n           \"10.5\",\n        ),\n       (tp.Units,\n           {\"units\": -10.5},\n           \"-10.5\",\n        ),\n       (tp.Units,\n           {\"units\": -10.55},\n           \"-10.55\",\n        ),\n       (tp.Units,\n           {\"units\": -12.655},\n           \"-10.55\",\n           ValueError\n        ),\n       # ClientID\n       (tp.ClientID,\n           {\"clientID\": \"my valid custom id\"},\n           \"my valid custom id\"\n        ),\n       (tp.ClientID,\n           {\"clientID\": \"to long\"+\"x\"*125},\n           \"to long\"+\"x\"*125,\n        ValueError\n        ),\n       # ClientTag\n       (tp.ClientTag,\n           {\"clientTag\": \"my valid custom tag\"},\n           \"my valid custom tag\"\n        ),\n       (tp.ClientTag,\n           {\"clientTag\": \"to long\"+\"x\"*125},\n           \"to long\"+\"x\"*125,\n        ValueError\n        ),\n       # ClientComment\n       (tp.ClientComment,\n           {\"clientComment\": \"my valid custom comment\"},\n           \"my valid custom comment\"\n        ),\n       (tp.ClientComment,\n           {\"clientComment\": \"to long\"+\"x\"*125},\n           \"to long\"+\"x\"*125,\n        ValueError\n        ),\n       # OrderIdentifier\n       (tp.OrderIdentifier,\n           {\"orderID\": 1234,\n            \"clientID\": \"my valid custom id\"},\n           {\"orderID\": \"1234\",\n            \"clientOrderID\": \"my valid custom id\"},\n        ),\n       (tp.OrderIdentifier,\n           {\"orderID\": \"X1234\",\n            \"clientID\": \"my valid custom id\"},\n           {\"orderID\": \"1234\",\n            \"clientOrderID\": \"my valid custom id\"},\n        ValueError\n        ),\n       (tp.OrderIdentifier,\n           {\"orderID\": \"1234\",\n            \"clientID\": \"to long\"+\"x\"*125},\n           {\"orderID\": \"1234\",\n            \"clientOrderID\": \"to long\"+\"x\"*125},\n        ValueError\n        ),\n       # OrderSpecifier\n       (tp.OrderSpecifier,\n           {\"specifier\": 1234},\n           \"1234\",\n        ),\n       (tp.OrderSpecifier,\n           {\"specifier\": \"1234\"},\n           \"1234\",\n        ),\n       (tp.OrderSpecifier,\n           {\"specifier\": \"@\"},\n           \"@\",\n        ValueError\n        ),\n       (tp.OrderSpecifier,\n           {\"specifier\": \"@my valid custom id\"},\n           \"my valid custom id\",\n        ),\n       (tp.OrderSpecifier,\n           {\"specifier\": \"@\"+\"to long\"+\"x\"*125},\n           \"to long\"+\"x\"*125,\n        ValueError\n        ),\n       # DateTime\n       # no sub-seconds\n       (tp.DateTime,\n           {\"dateTime\": \"2014-07-02T04:00:00Z\"},\n           \"2014-07-02T04:00:00Z\",\n        ),\n       # sub-seconds (milli)\n       (tp.DateTime,\n           {\"dateTime\": \"2014-07-02T04:00:00.000Z\"},\n           \"2014-07-02T04:00:00.000000Z\",\n        ),\n       # sub-seconds (micro)\n       (tp.DateTime,\n           {\"dateTime\": \"2014-07-02T04:00:00.000000Z\"},\n           \"2014-07-02T04:00:00.000000Z\",\n        ),\n       # sub-seconds (nano)\n       (tp.DateTime,\n           {\"dateTime\": \"2014-07-02T04:00:00.000000Z\"},\n           \"2014-07-02T04:00:00.000000Z\",\n        ),\n       # using a dict with date/time values\n       (tp.DateTime,\n           {\"dateTime\": {\"year\": 2014, \"month\": 12, \"day\": 2,\n                         \"hour\": 13, \"minute\": 48, \"second\": 12}},\n           \"2014-12-02T13:48:12Z\",\n        ),\n       # using a dict with date/time values + sub-seconds\n       (tp.DateTime,\n           {\"dateTime\": {\"year\": 2014, \"month\": 12, \"day\": 2,\n                         \"hour\": 13, \"minute\": 48, \"second\": 12,\n                         \"subsecond\": 0}},\n           \"2014-12-02T13:48:12.000000Z\",\n        ),\n       # using a datetime.datetime instance\n       (tp.DateTime,\n           {\"dateTime\": NOW},\n           datetime.strftime(NOW, \"%Y-%m-%dT%H:%M:%S.%fZ\")\n        ),\n       # test for exception (missing digit in seconds)\n       (tp.DateTime,\n           {\"dateTime\": \"2014-07-02T04:00:0\"},\n           \"2014-07-02T04:00:00.000000Z\",\n        ValueError\n        ),\n    ])\n    def test__types(self, cls, inpar, reference, exc=None):\n        \"\"\"test_types.\"\"\"\n        if not exc:\n            r = cls(**inpar)\n            self.assertTrue(r.value == reference)\n        else:\n            with self.assertRaises(exc) as err:\n                r = cls(**inpar)\n                self.assertTrue(\"ValueError\" in err)\n\n\nif __name__ == \"__main__\":\n\n    unittest.main()\n"
  },
  {
    "path": "tests/token.txt",
    "content": "aaaa9999bbbb8888cccc7777dddd6666-eeee5555ffff4444aaaa3333bbbb2222\n"
  },
  {
    "path": "tests/unittestsetup.py",
    "content": "\"\"\" initialization of unittests and data for unittests \"\"\"\n\nimport time\nenvironment = \"practice\"\n\n# calculate expiryDate as an offset from today\n# now + 5 days\ndays = 5\nexpiryDate = time.strftime(\"%Y-%m-%dT%H:%M:%S\",\n                           time.localtime(int(time.time() + 86400*days)))\n\n\ndef fetchTestData(responses, k):\n    resp = responses[k]['response']\n    params, data = None, None\n    if 'body' in responses[k]:\n        data = responses[k]['body']\n\n    if \"params\" in responses[k]:\n        params = responses[k]['params']\n\n    if params is not None:\n        return (resp, data, params)\n\n    return (resp, data)\n\n\nclass TestData(object):\n\n    def __init__(self, responses, tid):\n        self._responses = responses[tid]\n\n    @property\n    def resp(self):\n        return self._responses['response']\n\n    @property\n    def body(self):\n        return self._responses['body']\n\n    @property\n    def params(self):\n        return self._responses['params']\n\n\ndef auth():\n    access_token = None\n    account = None\n    currency = None\n    with open(\"tests/account.txt\") as A:\n        account, currency = A.read().strip().split(\"|\")\n    with open(\"tests/token.txt\") as T:\n        access_token = T.read().strip()\n\n    if account == \"99999999|EUR\":\n        raise Exception(\n              \"\\n\"\n              \"**************************************************\\n\"\n              \"*** PLEASE PROVIDE YOUR account in account.txt ***\\n\"\n              \"*** AND token IN token.txt TO RUN THE TESTS    ***\\n\"\n              \"**************************************************\\n\")\n\n    return account, currency, access_token\n"
  }
]