Skip to content

Commit

Permalink
Added basic logging capability to trading.py and related classes.
Browse files Browse the repository at this point in the history
  • Loading branch information
mhallsmoore committed Jul 13, 2015
1 parent 675412c commit 553edab
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 9 deletions.
11 changes: 8 additions & 3 deletions data/streaming.py
@@ -1,9 +1,11 @@
from __future__ import print_function

from decimal import Decimal, getcontext, ROUND_HALF_DOWN
import requests
import logging
import json

import requests

from qsforex.event.event import TickEvent
from qsforex.data.price import PriceHandler

Expand All @@ -19,6 +21,7 @@ def __init__(
self.events_queue = events_queue
self.pairs = pairs
self.prices = self._set_up_prices_dict()
self.logger = logging.getLogger(__name__)

def invert_prices(self, pair, bid, ask):
"""
Expand Down Expand Up @@ -63,10 +66,12 @@ def stream_to_queue(self):
dline = line.decode('utf-8')
msg = json.loads(dline)
except Exception as e:
print("Caught exception when converting message into json\n" + str(e))
self.logger.error(
"Caught exception when converting message into json: %s" % str(e)
)
return
if "instrument" in msg or "tick" in msg:
print(msg)
self.logger.debug(msg)
getcontext().rounding = ROUND_HALF_DOWN
instrument = msg["tick"]["instrument"].replace("_", "")
time = msg["tick"]["time"]
Expand Down
31 changes: 29 additions & 2 deletions event/event.py
Expand Up @@ -10,20 +10,47 @@ def __init__(self, instrument, time, bid, ask):
self.bid = bid
self.ask = ask

def __str__(self):
return "Type: %s, Instrument: %s, Time: %s, Bid: %s, Ask: %s" % (
str(self.type), str(self.instrument),
str(self.time), str(self.bid), str(self.ask)
)

def __repr__(self):
return str(self)


class SignalEvent(Event):
def __init__(self, instrument, order_type, side, time):
self.type = 'SIGNAL'
self.instrument = instrument
self.order_type = order_type
self.side = side
self.side = side
self.time = time # Time of the last tick that generated the signal

def __str__(self):
return "Type: %s, Instrument: %s, Order Type: %s, Side: %s" % (
str(self.type), str(self.instrument),
str(self.order_type), str(self.side)
)

def __repr__(self):
return str(self)


class OrderEvent(Event):
def __init__(self, instrument, units, order_type, side):
self.type = 'ORDER'
self.instrument = instrument
self.units = units
self.order_type = order_type
self.side = side
self.side = side

def __str__(self):
return "Type: %s, Instrument: %s, Units: %s, Order Type: %s, Side: %s" % (
str(self.type), str(self.instrument), str(self.units),
str(self.order_type), str(self.side)
)

def __repr__(self):
return str(self)
6 changes: 4 additions & 2 deletions execution/execution.py
Expand Up @@ -5,6 +5,7 @@
import httplib
except ImportError:
import http.client as httplib
import logging
try:
from urllib import urlencode
except ImportError:
Expand Down Expand Up @@ -47,6 +48,7 @@ def __init__(self, domain, access_token, account_id):
self.access_token = access_token
self.account_id = account_id
self.conn = self.obtain_connection()
self.logger = logging.getLogger(__name__)

def obtain_connection(self):
return httplib.HTTPSConnection(self.domain)
Expand All @@ -68,6 +70,6 @@ def execute_order(self, event):
"/v1/accounts/%s/orders" % str(self.account_id),
params, headers
)
response = self.conn.getresponse().read()
print(response)
response = self.conn.getresponse().read().decode("utf-8").replace("\n","").replace("\t","")
self.logger.debug(response)

28 changes: 28 additions & 0 deletions logging.conf
@@ -0,0 +1,28 @@
[loggers]
keys=root,qsforex.trading.trading

[handlers]
keys=consoleHandler

[formatters]
keys=simpleFormatter

[logger_root]
level=DEBUG
handlers=consoleHandler

[logger_qsforex.trading.trading]
level=DEBUG
handlers=consoleHandler
qualname=qsforex.trading.trading
propagate=0

[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)

[formatter_simpleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
datefmt=
7 changes: 5 additions & 2 deletions portfolio/portfolio.py
Expand Up @@ -2,6 +2,7 @@

from copy import deepcopy
from decimal import Decimal, getcontext, ROUND_HALF_DOWN
import logging
import os

import pandas as pd
Expand Down Expand Up @@ -30,6 +31,7 @@ def __init__(
self.positions = {}
if self.backtest:
self.backtest_file = self.create_equity_file()
self.logger = logging.getLogger(__name__)

def calc_risk_position_size(self):
return self.equity * self.risk_per_trade
Expand Down Expand Up @@ -184,7 +186,8 @@ def execute_signal(self, signal_event):

order = OrderEvent(currency_pair, units, "market", side)
self.events.put(order)
print("Balance: ", self.balance)

self.logger.info("Portfolio Balance: %s" % self.balance)
else:
print("Unable to execute order as price data was insufficient.")
self.logger.info("Unable to execute order as price data was insufficient.")

11 changes: 11 additions & 0 deletions trading/trading.py
@@ -1,5 +1,7 @@
import copy
from decimal import Decimal, getcontext
import logging
import logging.config
try:
import Queue as queue
except ImportError:
Expand Down Expand Up @@ -30,16 +32,23 @@ def trade(events, strategy, portfolio, execution, heartbeat):
else:
if event is not None:
if event.type == 'TICK':
logger.info("Received new tick event: %s", event)
strategy.calculate_signals(event)
portfolio.update_portfolio(event)
elif event.type == 'SIGNAL':
logger.info("Received new signal event: %s", event)
portfolio.execute_signal(event)
elif event.type == 'ORDER':
logger.info("Received new order event: %s", event)
execution.execute_order(event)
time.sleep(heartbeat)


if __name__ == "__main__":
# Set up logging
logging.config.fileConfig('../logging.conf')
logger = logging.getLogger('qsforex.trading.trading')

# Set the number of decimal places to 2
getcontext().prec = 2

Expand Down Expand Up @@ -86,5 +95,7 @@ def trade(events, strategy, portfolio, execution, heartbeat):
price_thread = threading.Thread(target=prices.stream_to_queue, args=[])

# Start both threads
logger.info("Starting trading thread")
trade_thread.start()
logger.info("Starting price streaming thread")
price_thread.start()

0 comments on commit 553edab

Please sign in to comment.