Skip to content

Commit

Permalink
Merge pull request #17 from alpacahq/feature/clock
Browse files Browse the repository at this point in the history
Clock/Calendar API support
  • Loading branch information
umitanuki authored Jun 12, 2018
2 parents 35e2c59 + 2411dcf commit b32ceff
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 10 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,12 @@ Calls `GET /assets` and returns a list of `Asset` entities.
### REST.get_asset(symbol)
Calls `GET /assets/{symbol}` and returns an `Asset` entity.

### REST.get_clock()
Calls `GET /clock` and returns a `Clock` entity.

### REST.get_calendar(start=None, end=None)
Calls `GET /calendar` and returns a `Calendar` entity.

### REST.list_quotes(symbols)
Calls `GET /quotes` with symbols and returns a list of `Quote` entities. If `symbols` is not a string, it is concatenated with commas.

Expand Down
40 changes: 38 additions & 2 deletions alpaca_trade_api/rest.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import dateutil.parser
import pandas as pd
import pprint
import re
Expand Down Expand Up @@ -206,6 +205,19 @@ def get_bars(
resp = self.get('/assets/{}/bars'.format(symbol), params)
return AssetBars(resp)

def get_clock(self):
resp = self.get('/clock')
return Clock(resp)

def get_calendar(self, start=None, end=None):
params = {}
if start is not None:
params['start'] = start
if end is not None:
params['end'] = end
resp = self.get('/calendar', data=params)
return [Calendar(o) for o in resp]


class Entity(object):
'''This helper class provides property access (the "dot notation")
Expand All @@ -224,7 +236,7 @@ def __getattr__(self, key):
key.endswith('_timestamp') or
key.endswith('_time')) and
ISO8601YMD.match(val)):
return dateutil.parser.parse(val)
return pd.Timestamp(val)
else:
return val
return getattr(super(), key)
Expand Down Expand Up @@ -298,3 +310,27 @@ class Quote(Entity):

class Fundamental(Entity):
pass


class Clock(Entity):
def __getattr__(self, key):
if key in self._raw:
val = self._raw[key]
if key in ('timestamp', 'next_open', 'next_close'):
return pd.Timestamp(val)
else:
return val
return getattr(super(), key)


class Calendar(Entity):
def __getattr__(self, key):
if key in self._raw:
val = self._raw[key]
if key in ('date',):
return pd.Timestamp(val)
elif key in ('open', 'close'):
return pd.Timestamp(val).time()
else:
return val
return getattr(super(), key)
43 changes: 37 additions & 6 deletions tests/test_rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,10 +197,9 @@ def test_orders(reqmock):
# Get an order by client order id
client_order_id = 'client-order-id'
reqmock.get(
'https://api.alpaca.markets/v1/orders:by_client_order_id?client_order_id={}'.format(
client_order_id,
),
text='''{
'https://api.alpaca.markets/v1/orders:by_client_order_id?'
'client_order_id={}'.format(
client_order_id, ), text='''{
"id": "904837e3-3b76-47ec-b432-046db621571b",
"client_order_id": "904837e3-3b76-47ec-b432-046db621571b",
"account_id": "904837e3-3b76-47ec-b432-046db621571b",
Expand All @@ -223,8 +222,7 @@ def test_orders(reqmock):
"failured_reason": "string",
"cancel_requested_at": "2018-03-09T05:50:50Z",
"submitted_at": "2018-03-09T05:50:50Z"
}'''
)
}''')
order = api.get_order_by_client_order_id(client_order_id)
assert order.submitted_at.minute == 50

Expand Down Expand Up @@ -311,6 +309,39 @@ def test_positions(reqmock):
assert position.cost_basis == '500.0'


def test_chronos(reqmock):
api = tradeapi.REST('key-id', 'secret-key')

# clock
reqmock.get(
'https://api.alpaca.markets/v1/clock',
text='''{
"timestamp": "2018-04-01T12:00:00.000Z",
"is_open": true,
"next_open": "2018-04-01T12:00:00.000Z",
"next_close": "2018-04-01T12:00:00.000Z"
}'''
)
clock = api.get_clock()
assert clock.is_open
assert clock.next_open.day == 1

# calendar
reqmock.get(
'https://api.alpaca.markets/v1/calendar?start=2018-01-03',
text='''[
{
"date": "2018-01-03",
"open": "09:30",
"close": "16:00"
}
]'''
)
calendar = api.get_calendar(start='2018-01-03')
assert calendar[0].date.day == 3
assert calendar[0].open.minute == 30


def test_assets(reqmock):
api = tradeapi.REST('key-id', 'secret-key')
# Bars
Expand Down
4 changes: 2 additions & 2 deletions tests/test_stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
import json
import pytest
try:
from unittest.mock import patch
from unittest.mock import patch
except ImportError:
from mock import patch
from mock import patch
from websocket import WebSocketConnectionClosedException


Expand Down

0 comments on commit b32ceff

Please sign in to comment.