mirror of
https://github.com/bspeice/metrik
synced 2024-11-23 07:38:09 -05:00
Add Tradeking functionality
Yet to be integrated with the Equities flow, hold your horses.
This commit is contained in:
parent
65de3a782a
commit
0d249af584
@ -24,6 +24,13 @@
|
|||||||
</value>
|
</value>
|
||||||
</option>
|
</option>
|
||||||
</inspection_tool>
|
</inspection_tool>
|
||||||
|
<inspection_tool class="PyShadowingBuiltinsInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
|
||||||
|
<option name="ignoredNames">
|
||||||
|
<list>
|
||||||
|
<option value="format" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</inspection_tool>
|
||||||
<inspection_tool class="PyUnresolvedReferencesInspection" enabled="false" level="WARNING" enabled_by_default="false">
|
<inspection_tool class="PyUnresolvedReferencesInspection" enabled="false" level="WARNING" enabled_by_default="false">
|
||||||
<option name="ignoredIdentifiers">
|
<option name="ignoredIdentifiers">
|
||||||
<list>
|
<list>
|
||||||
|
BIN
.metrik.enc
Normal file
BIN
.metrik.enc
Normal file
Binary file not shown.
@ -10,5 +10,8 @@ services:
|
|||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- export TZ=America/New_York
|
- export TZ=America/New_York
|
||||||
|
# Encrypted .metrik.enc file contains credentials for services that are behind OAuth, etc.
|
||||||
|
- openssl aes-256-cbc -K $encrypted_4cca49abdb96_key -iv $encrypted_4cca49abdb96_iv -in .metrik.enc -out ~\/.metrik -d
|
||||||
|
|
||||||
install: pip install -r requirements.txt
|
install: pip install -r requirements.txt
|
||||||
script: python setup.py test
|
script: python setup.py test
|
@ -1,2 +1,2 @@
|
|||||||
__version__ = '0.2.3'
|
__version__ = '0.3.0'
|
||||||
__release__ = __version__
|
__release__ = __version__
|
82
metrik/tasks/tradeking.py
Normal file
82
metrik/tasks/tradeking.py
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
import requests
|
||||||
|
from requests_oauthlib import OAuth1Session
|
||||||
|
from luigi.parameter import DateParameter, Parameter
|
||||||
|
from datetime import timedelta
|
||||||
|
from dateutil.parser import parse
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from metrik.tasks.base import MongoCreateTask, MongoRateLimit
|
||||||
|
from metrik.conf import get_config
|
||||||
|
|
||||||
|
|
||||||
|
class TradekingApi(object):
|
||||||
|
|
||||||
|
format_json = '.json'
|
||||||
|
format_xml = '.xml'
|
||||||
|
root_url = 'https://api.tradeking.com/v1/'
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
config = get_config()
|
||||||
|
self.session = OAuth1Session(
|
||||||
|
client_key=config.get('tradeking', 'consumer_key'),
|
||||||
|
client_secret=config.get('tradeking', 'consumer_secret'),
|
||||||
|
resource_owner_key=config.get('tradeking', 'oauth_token'),
|
||||||
|
resource_owner_secret=config.get('tradeking', 'oauth_token_secret')
|
||||||
|
)
|
||||||
|
|
||||||
|
def api_request(self, url, params=None, format=format_json, **kwargs):
|
||||||
|
full_url = self.root_url + url + format
|
||||||
|
return self.session.get(full_url, params=params, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class Tradeking1mTimesales(MongoCreateTask):
|
||||||
|
# While this is marked as an idempotent task, it only goes back about
|
||||||
|
# a week or so. Be careful.
|
||||||
|
present = DateParameter()
|
||||||
|
symbol = Parameter()
|
||||||
|
|
||||||
|
def acquire_lock(self, service, limit, interval, max_tries=5, backoff=.5):
|
||||||
|
return super(Tradeking1mTimesales, self).acquire_lock(
|
||||||
|
'tradeking', 60, timedelta(minutes=1)
|
||||||
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def retrieve_data(present, symbol):
|
||||||
|
ratelimit = MongoRateLimit()
|
||||||
|
tradeking = TradekingApi()
|
||||||
|
did_acquire = ratelimit.acquire_lock(
|
||||||
|
service='tradeking',
|
||||||
|
limit=60,
|
||||||
|
interval=timedelta(minutes=1)
|
||||||
|
)
|
||||||
|
if did_acquire:
|
||||||
|
json_data = tradeking.api_request('market/timesales', {
|
||||||
|
'symbols': symbol,
|
||||||
|
'interval': '1min',
|
||||||
|
'startdate': present.strftime('%Y-%m-%d'),
|
||||||
|
'enddate': present.strftime('%Y-%m-%d')
|
||||||
|
}).json()
|
||||||
|
|
||||||
|
quotes = json_data['response']['quotes']['quote']
|
||||||
|
def format_quote(quote):
|
||||||
|
return {
|
||||||
|
'last': float(quote['last']),
|
||||||
|
'lo': float(quote['lo']),
|
||||||
|
'vl': int(quote['vl']),
|
||||||
|
'datetime': parse(quote['datetime']),
|
||||||
|
'incr_vl': int(quote['incr_vl']),
|
||||||
|
'hi': float(quote['hi']),
|
||||||
|
'timestamp': parse(quote['timestamp']),
|
||||||
|
'date': parse(quote['date']).date(),
|
||||||
|
'opn': float(quote['opn'])
|
||||||
|
}
|
||||||
|
quotes_typed = [format_quote(q) for q in quotes]
|
||||||
|
|
||||||
|
return {
|
||||||
|
'symbol': symbol,
|
||||||
|
'quotes': quotes_typed
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
logging.error('Unable to acquire lock for Tradeking ticker {}'
|
||||||
|
.format(symbol))
|
||||||
|
return {}
|
3
setup.py
3
setup.py
@ -26,7 +26,8 @@ setup(
|
|||||||
],
|
],
|
||||||
tests_require=[
|
tests_require=[
|
||||||
'pytest',
|
'pytest',
|
||||||
'pytest-catchlog'
|
'pytest-catchlog',
|
||||||
|
'pandas-datareader'
|
||||||
],
|
],
|
||||||
entry_points={
|
entry_points={
|
||||||
'console_scripts': [
|
'console_scripts': [
|
||||||
|
37
test/tasks/test_tradeking.py
Normal file
37
test/tasks/test_tradeking.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
from unittest import TestCase
|
||||||
|
from datetime import datetime
|
||||||
|
from pandas_datareader.data import get_data_yahoo
|
||||||
|
from numpy.testing import assert_allclose
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from metrik.tasks.tradeking import Tradeking1mTimesales
|
||||||
|
from metrik.trading_days import TradingDay
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('ticker', [
|
||||||
|
'AAPL', 'GOOG', 'SPY', 'REGN', 'SWHC', 'BAC', 'NVCR'
|
||||||
|
])
|
||||||
|
def test_returns_verifiable(ticker):
|
||||||
|
# Test that the quotes line up with data off of Yahoo
|
||||||
|
now = datetime.now()
|
||||||
|
prior_day = now - TradingDay(1)
|
||||||
|
|
||||||
|
quotes = Tradeking1mTimesales.retrieve_data(prior_day, ticker)
|
||||||
|
|
||||||
|
yahoo_ohlc = map(tuple, get_data_yahoo(ticker, prior_day, prior_day)[
|
||||||
|
['Open', 'High', 'Low', 'Close']
|
||||||
|
].values)[0]
|
||||||
|
|
||||||
|
open = high = close = 0
|
||||||
|
low = 999999
|
||||||
|
for index, quote in enumerate(quotes['quotes']):
|
||||||
|
if index == 0:
|
||||||
|
open = quote['opn']
|
||||||
|
if index == len(quotes['quotes']) - 1:
|
||||||
|
close = quote['last']
|
||||||
|
high = max(high, quote['hi'])
|
||||||
|
low = min(low, quote['lo'])
|
||||||
|
|
||||||
|
tradeking_ohlc = (open, high, low, close)
|
||||||
|
|
||||||
|
assert_allclose(tradeking_ohlc, yahoo_ohlc, rtol=1e-3)
|
Loading…
Reference in New Issue
Block a user