Skip to content

Commit

Permalink
Cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
Tomasz Dziopa committed Jul 5, 2018
1 parent c07b29a commit 7ee4229
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 91 deletions.
77 changes: 54 additions & 23 deletions client.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,8 @@

import requests

### CONFIG
from config import configuration

BASE_URL = 'https://api.smarkets.com/v3/'
LOGIN = ''
PASSWORD = ''

### RUNTIME CONSTANTS
CHUNK_SIZE = 20

# fileConfig('logging.config')
log = logging.getLogger(__name__)

class SmarketsClient:
Expand All @@ -29,14 +21,21 @@ def _auth_headers(self):
def init_session(self):
log.info('initiating session')
with self.auth_lock:
response = requests.post(f'{BASE_URL}sessions/', json={'username': LOGIN, 'password': PASSWORD}).json()
response = requests.post(
f'{configuration["api"]["base_url"]}sessions/',
json={
'username': configuration['auth']['login'],
'password': configuration['auth']['password'],
},
).json()
self.auth_token = response.get('token')
log.info(f'new auth token: {self.auth_token}')

def reauth_session(self):
log.info('renewing session')
with self.auth_lock:
response = requests.post(f'{BASE_URL}sessions/reauth/').json()
response = requests.post(f'{configuration["api"]["base_url"]}sessions/reauth/').json()
self.auth_token = response.get('token')
log.info(f'new auth token: {self.auth_token}')

def place_bet(
Expand All @@ -47,9 +46,10 @@ def place_bet(
quantity,
side,
):
log.info(f'placing order: m_id {market_id}: c_id {contract_id} \t {side} {quantity} @ {price}')
with self.auth_lock:
response = requests.post(
f'{BASE_URL}orders/',
f'{configuration["api"]["base_url"]}orders/',
json={
'market_id': market_id,
'contract_id': contract_id,
Expand All @@ -60,23 +60,27 @@ def place_bet(
},
headers=self._auth_headers(),
).json()
log.info(response)
log.info(
f'''order placed: m_id {market_id}: c_id {contract_id} \t {side} {quantity} @ {price}|'''
f'''balance:{response["available_balance"]} executed:{response["total_executed_quantity"]}'''
f''' exposure:{response["exposure"]}'''
)

def cancel_bet(self, order_id):
with self.auth_lock:
response = requests.delete(
f'{BASE_URL}orders/{order_id}/',
f'{configuration["api"]["base_url"]}orders/{order_id}/',
headers=self._auth_headers(),
)

def get_orders(self, states):
orders = []
states_to_fetch = '&'.join([f'states={state}' for state in states])
next_page = f'?limit={CHUNK_SIZE}&{states_to_fetch}'
next_page = f'?limit={configuration["api"]["chunk_size"]}&{states_to_fetch}'
with self.auth_lock:
while next_page:
response = requests.get(
f'{BASE_URL}orders/{next_page}',
f'{configuration["api"]["base_url"]}orders/{next_page}',
headers=self._auth_headers(),
).json()
log.info(response)
Expand All @@ -96,7 +100,7 @@ def get_available_events(
page_filter = f'?{states_filter}&{types_filter}&sort=id&limit={limit}'
events = []
while page_filter:
request_url = f'{BASE_URL}events/{page_filter}'
request_url = f'{configuration["api"]["base_url"]}events/{page_filter}'
current_page = self._client_wrapper(request_url)
events += current_page['events']
page_filter = current_page['pagination']['next_page']
Expand All @@ -107,19 +111,24 @@ def get_related_markets(self, events):
markets = []
event_ids = [event['id'] for event in events]
i = 0
while i*CHUNK_SIZE < len(event_ids):
events_to_fetch = ','.join(event_ids[i*CHUNK_SIZE:(i+1)*CHUNK_SIZE])
request_url = f'{BASE_URL}events/{events_to_fetch}/markets/?sort=event_id,display_order&limit_by_event=1&with_volumes=true'
while i*configuration["api"]["chunk_size"] < len(event_ids):
events_to_fetch = ','.join(
event_ids[i*configuration["api"]["chunk_size"]:(i+1)*configuration["api"]["chunk_size"]]
)
request_url = f'''{configuration["api"]["base_url"]}events/{events_to_fetch}/markets/'''
f'''?sort=event_id,display_order&limit_by_event=1&with_volumes=true'''
markets += self._client_wrapper(request_url)['markets']
i += 1
return markets

def get_quotes(self, market_ids):
quotes = []
i = 0
while i*CHUNK_SIZE < len(market_ids):
markets_to_fetch = ','.join(market_ids[i*CHUNK_SIZE:(i+1)*CHUNK_SIZE])
request_url = f'{BASE_URL}markets/{markets_to_fetch}/quotes/'
while i*configuration["api"]["chunk_size"] < len(market_ids):
markets_to_fetch = ','.join(
market_ids[i*configuration["api"]["chunk_size"]:(i+1)*configuration["api"]["chunk_size"]]
)
request_url = f'{configuration["api"]["base_url"]}markets/{markets_to_fetch}/quotes/'
quotes += [self._client_wrapper(request_url)]
i+=1
quotes_result = {}
Expand All @@ -128,6 +137,28 @@ def get_quotes(self, market_ids):
quotes_result[contract_id] = order_book
return quotes_result

def get_accounts(self):
response = None
with self.auth_lock:
response = requests.get(
f'{configuration["api"]["base_url"]}accounts/', headers=self._auth_headers()
).json()
return response

def get_account_activity(self, market_id=None):
market_filter = '' if not market_id else f'&market_id={market_id}'
next_page = f'?limit={configuration["api"]["chunk_size"]}{market_filter}'
activity = []
while next_page:
with self.auth_lock:
response = requests.get(
f'{configuration["api"]["base_url"]}accounts/activity/{next_page}',
headers=self._auth_headers(),
).json()
activity += response['account_activity']
next_page = response['pagination']['next_page']
return activity

def _client_wrapper(self, url: str) -> Dict[str, Any]:
log.info(f'calling url: {url}')
return requests.get(url).json()
3 changes: 3 additions & 0 deletions config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import toml

configuration = toml.load('configuration.toml')
13 changes: 13 additions & 0 deletions configuration_template.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[auth]
login = "your_login_here"
password = "password_plz"

[api]
base_url = "https://api.smarkets.com/v3/"
# base_url = "https://api.smarkets-dev.com/v3/" # for sandbox
chunk_size = 20

[misc]
sleep_interval = 10
reauth_sleep_interval = 600
ticker_plant_path = "tickerplant.db"
7 changes: 4 additions & 3 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import requests

import utils
from config import configuration
from client import SmarketsClient


Expand All @@ -30,10 +31,10 @@ def run(self):
self.authenticator = utils.Authenticator(self.smk_client)
self.authenticator.start()
# if not self.the_bot or not self.the_bot.is_alive():
# self.the_bot = trading.DumbBot(auth_lock, auth_token)
# self.the_bot = trading.DumbBot(self.smk_client)
# self.the_bot.start()
log.info(f'babysitting threads for {utils.SLEEP_INTERVAL} seconds')
time.sleep(utils.SLEEP_INTERVAL)
log.info(f'babysitting threads for {configuration["misc"]["sleep_interval"]} seconds')
time.sleep(configuration["misc"]["sleep_interval"])

def main():
TradingBot().run()
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ certifi==2018.4.16
chardet==3.0.4
idna==2.7
requests==2.19.1
toml==0.9.4
urllib3==1.23
80 changes: 28 additions & 52 deletions trading.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,72 +4,48 @@
from collections import defaultdict
from itertools import groupby
from logging.config import fileConfig
from pprint import pprint

import requests

import utils
import client

# fileConfig('logging.config')

fileConfig('logging.config', disable_existing_loggers=False)
log = logging.getLogger(__name__)

class DumbBot(threading.Thread):
def __init__(self, smk_client):
self.smk_client = smk_client

def calculate_ev(self):
orders = self.smk_client.get_orders(states=['filled', 'partial'])
unique_markets = set([order['market_id'] for order in orders])
unique_markets_quotes = self.smk_client.get_quotes(list(unique_markets))
log.info(unique_markets_quotes)
contract_book = defaultdict(list)
# instantiate client: single instance per session
client = client.SmarketsClient()

for contract_id, order in groupby(orders, lambda x: x['contract_id']):
self._calculate_contract_ev(list(orders), unique_markets_quotes.get(contract_id))
# contract_book[order['contract_id']].append({
# 'price': (10000.0 / order['average_price_matched']),
# 'stake': (order['quantity_filled'] / (10000.0 / order['average_price_matched'])),
# 'ev': (order['quantity_filled'] / (10000.0 / order['average_price_matched'])) *
# })
log.info(contract_book)
def _calculate_contract_ev(self, contract_orders, quotes):
order_prices = [
{
'price': 10000.0 / order['average_price_matched'],
'stake': order['quantity_filled'] / (10000.0 / order['average_price_matched']),
'side': order['side'],
}
for order in contract_orders
]
quotes = {
'sell': 10000.0 / max(tick['price'] for tick in quotes['bids']),
'buy': 10000.0 / min(tick['price'] for tick in quotes['offers']),
}
log.info(order_prices)
log.info(quotes)
log.info([
(100.0 / (quotes['sell'] if o['side']=='buy' else quotes['buy']) - 100.0/ o['price']) * o['stake']
for o
in order_prices
])
# do initial authentication
client.init_session()

def run(self):
pass

# pick some market and contract
market_id = '6672405'
contract_id = '21490523'

client = client.SmarketsClient()
# place some bets
# don't worry about the price: the buy price is set to be very high
# it's very unlikely someone will match you :)

client.init_session()
# client.place_bet(
# "6672405",
# "21490523",
# 50,
# 50000,
# 'buy',
# )
client.place_bet(
market_id, # market id
contract_id, # contract id
50, # percentage price * 10**4, here: 0.5% / 200 decimal / 19900 american
500000, # quantity: total stake * 10**4, here: 50 GBP. Your buy order locks 0.25 GBP, as
# 0.25 GBP * 200 = 50 GBP
'buy', # order side: buy or sell
)

# client.cancel_bet('202547466272702478')

log.info(client.get_orders(states=['created', 'filled', 'partial']))
log.info(DumbBot(client).calculate_ev())
# lets get the orders now!
pprint(client.get_orders(states=['created', 'filled', 'partial']))

pprint(client.get_accounts())
pprint(client.get_account_activity(market_id))

# eeh, changed my mind
# client.cancel_bet('202547466272702478')
20 changes: 7 additions & 13 deletions utils.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,14 @@
import logging
from typing import Any, Dict, List
import datetime
import sqlite3
import threading
import time

from logging.config import fileConfig
from typing import Any, Dict, List

import requests

### RUNTIME CONSTANTS
TICKER_PLANT_PATH = 'tickerplant.db'
REAUTH_SLEEP_INTERVAL = 600
SLEEP_INTERVAL = 10

from config import configuration

log = logging.getLogger(__name__)

Expand All @@ -23,7 +18,7 @@ def __init__(self, smk_client):
super().__init__()

def _initialize_ticker_plant(self):
connection = sqlite3.connect(TICKER_PLANT_PATH)
connection = sqlite3.connect(configuration["misc"]["ticker_plant_path"])
with connection:
connection.execute("""
CREATE TABLE IF NOT EXISTS ticks (
Expand Down Expand Up @@ -71,7 +66,7 @@ def flatten_order_book(order_book):
]),
)

connection = sqlite3.connect(TICKER_PLANT_PATH)
connection = sqlite3.connect(configuration["misc"]["ticker_plant_path"])
with connection:
connection.executemany(
"""
Expand All @@ -97,8 +92,8 @@ def run(self):
while True:
quotes = self.smk_client.get_quotes([market['id'] for market in markets])
self._store_ticks(quotes)
log.info(f'collected the ticks, now sleeping for {SLEEP_INTERVAL} seconds')
time.sleep(SLEEP_INTERVAL)
log.info(f'collected the ticks, now sleeping for {configuration["misc"]["sleep_interval"]} seconds')
time.sleep(configuration["misc"]["sleep_interval"])


class Authenticator(threading.Thread):
Expand All @@ -109,6 +104,5 @@ def __init__(self, smk_client):
def run(self):
self.smk_client.init_session()
while True:
log.info('hej')
time.sleep(REAUTH_SLEEP_INTERVAL)
time.sleep(configuration["misc"]["reauth_sleep_interval"])
self.smk_client.reauth_session()

0 comments on commit 7ee4229

Please sign in to comment.