Added Python 2.7.x and 3.4.x compatibility to the code. Disabled HTTPS security warning in urllib3 package of 'requests' package.

This commit is contained in:
Michael Halls-Moore
2015-05-11 17:30:28 +01:00
parent 8e74edb4f7
commit a03bc7a1fb
9 changed files with 67 additions and 39 deletions
+1
View File
@@ -1,5 +1,6 @@
*~ *~
*.py[co] *.py[co]
__pycache__
# Packages # Packages
*.egg *.egg
+9 -4
View File
@@ -1,5 +1,10 @@
from __future__ import print_function
import copy import copy
import Queue try:
import Queue as queue
except ImportError:
import queue
import threading import threading
import time import time
from decimal import Decimal, getcontext from decimal import Decimal, getcontext
@@ -28,7 +33,7 @@ def backtest(
ticker.stream_next_tick() ticker.stream_next_tick()
try: try:
event = events.get(False) event = events.get(False)
except Queue.Empty: except queue.Empty:
pass pass
else: else:
if event is not None: if event is not None:
@@ -45,14 +50,14 @@ def backtest(
if __name__ == "__main__": if __name__ == "__main__":
heartbeat = 0.0 heartbeat = 0.0
events = Queue.Queue() events = queue.Queue()
equity = settings.EQUITY equity = settings.EQUITY
# Load the historic CSV tick data files # Load the historic CSV tick data files
pairs = ["GBPUSD"] pairs = ["GBPUSD"]
csv_dir = settings.CSV_DATA_DIR csv_dir = settings.CSV_DATA_DIR
if csv_dir is None: if csv_dir is None:
print "No historic data directory provided - backtest terminating." print("No historic data directory provided - backtest terminating.")
sys.exit() sys.exit()
# Create the historic tick data streaming class # Create the historic tick data streaming class
+8 -6
View File
@@ -1,5 +1,5 @@
import datetime import datetime
from decimal import Decimal, ROUND_HALF_DOWN from decimal import Decimal, getcontext, ROUND_HALF_DOWN
import os import os
import os.path import os.path
import time import time
@@ -59,12 +59,13 @@ class PriceHandler(object):
This will turn the bid/ask of "GBPUSD" into bid/ask for This will turn the bid/ask of "GBPUSD" into bid/ask for
"USDGBP" and place them in the prices dictionary. "USDGBP" and place them in the prices dictionary.
""" """
getcontext().rounding = ROUND_HALF_DOWN
inv_pair = "%s%s" % (pair[3:], pair[:3]) inv_pair = "%s%s" % (pair[3:], pair[:3])
inv_bid = (Decimal("1.0")/bid).quantize( inv_bid = (Decimal("1.0")/bid).quantize(
Decimal("0.00001", ROUND_HALF_DOWN) Decimal("0.00001")
) )
inv_ask = (Decimal("1.0")/ask).quantize( inv_ask = (Decimal("1.0")/ask).quantize(
Decimal("0.00001", ROUND_HALF_DOWN) Decimal("0.00001")
) )
return inv_pair, inv_bid, inv_ask return inv_pair, inv_bid, inv_ask
@@ -129,16 +130,17 @@ class HistoricCSVPriceHandler(PriceHandler):
well as updating the current bid/ask and inverse bid/ask. well as updating the current bid/ask and inverse bid/ask.
""" """
try: try:
index, row = self.all_pairs.next() index, row = next(self.all_pairs)
except StopIteration: except StopIteration:
return return
else: else:
getcontext().rounding = ROUND_HALF_DOWN
pair = row["Pair"] pair = row["Pair"]
bid = Decimal(str(row["Bid"])).quantize( bid = Decimal(str(row["Bid"])).quantize(
Decimal("0.00001", ROUND_HALF_DOWN) Decimal("0.00001")
) )
ask = Decimal(str(row["Ask"])).quantize( ask = Decimal(str(row["Ask"])).quantize(
Decimal("0.00001", ROUND_HALF_DOWN) Decimal("0.00001")
) )
# Create decimalised prices for traded pair # Create decimalised prices for traded pair
+16 -10
View File
@@ -1,4 +1,6 @@
from decimal import Decimal, ROUND_HALF_DOWN from __future__ import print_function
from decimal import Decimal, getcontext, ROUND_HALF_DOWN
import requests import requests
import json import json
@@ -24,18 +26,20 @@ class StreamingForexPrices(PriceHandler):
This will turn the bid/ask of "GBPUSD" into bid/ask for This will turn the bid/ask of "GBPUSD" into bid/ask for
"USDGBP" and place them in the prices dictionary. "USDGBP" and place them in the prices dictionary.
""" """
getcontext().rounding = ROUND_HALF_DOWN
inv_pair = "%s%s" % (pair[3:], pair[:3]) inv_pair = "%s%s" % (pair[3:], pair[:3])
inv_bid = (Decimal("1.0")/bid).quantize( inv_bid = (Decimal("1.0")/bid).quantize(
Decimal("0.00001", ROUND_HALF_DOWN) Decimal("0.00001")
) )
inv_ask = (Decimal("1.0")/ask).quantize( inv_ask = (Decimal("1.0")/ask).quantize(
Decimal("0.00001", ROUND_HALF_DOWN) Decimal("0.00001")
) )
return inv_pair, inv_bid, inv_ask return inv_pair, inv_bid, inv_ask
def connect_to_stream(self): def connect_to_stream(self):
pairs_oanda = ["%s_%s" % (p[:3], p[3:]) for p in self.pairs] pairs_oanda = ["%s_%s" % (p[:3], p[3:]) for p in self.pairs]
try: try:
requests.packages.urllib3.disable_warnings()
s = requests.Session() s = requests.Session()
url = "https://" + self.domain + "/v1/prices" url = "https://" + self.domain + "/v1/prices"
headers = {'Authorization' : 'Bearer ' + self.access_token} headers = {'Authorization' : 'Bearer ' + self.access_token}
@@ -46,7 +50,7 @@ class StreamingForexPrices(PriceHandler):
return resp return resp
except Exception as e: except Exception as e:
s.close() s.close()
print "Caught exception when connecting to stream\n" + str(e) print("Caught exception when connecting to stream\n" + str(e))
def stream_to_queue(self): def stream_to_queue(self):
response = self.connect_to_stream() response = self.connect_to_stream()
@@ -55,19 +59,21 @@ class StreamingForexPrices(PriceHandler):
for line in response.iter_lines(1): for line in response.iter_lines(1):
if line: if line:
try: try:
msg = json.loads(line) dline = line.decode('utf-8')
msg = json.loads(dline)
except Exception as e: except Exception as e:
print "Caught exception when converting message into json\n" + str(e) print("Caught exception when converting message into json\n" + str(e))
return return
if msg.has_key("instrument") or msg.has_key("tick"): if "instrument" in msg or "tick" in msg:
print msg print(msg)
getcontext().rounding = ROUND_HALF_DOWN
instrument = msg["tick"]["instrument"].replace("_", "") instrument = msg["tick"]["instrument"].replace("_", "")
time = msg["tick"]["time"] time = msg["tick"]["time"]
bid = Decimal(str(msg["tick"]["bid"])).quantize( bid = Decimal(str(msg["tick"]["bid"])).quantize(
Decimal("0.00001", ROUND_HALF_DOWN) Decimal("0.00001")
) )
ask = Decimal(str(msg["tick"]["ask"])).quantize( ask = Decimal(str(msg["tick"]["ask"])).quantize(
Decimal("0.00001", ROUND_HALF_DOWN) Decimal("0.00001")
) )
self.prices[instrument]["bid"] = bid self.prices[instrument]["bid"] = bid
self.prices[instrument]["ask"] = ask self.prices[instrument]["ask"] = ask
+14 -4
View File
@@ -1,6 +1,16 @@
from __future__ import print_function
from abc import ABCMeta, abstractmethod from abc import ABCMeta, abstractmethod
import httplib try:
import urllib import httplib
except ImportError:
import http.client as httplib
try:
from urllib import urlencode
except ImportError:
from urllib.parse import urlencode
import urllib3
urllib3.disable_warnings()
class ExecutionHandler(object): class ExecutionHandler(object):
@@ -47,7 +57,7 @@ class OANDAExecutionHandler(ExecutionHandler):
"Content-Type": "application/x-www-form-urlencoded", "Content-Type": "application/x-www-form-urlencoded",
"Authorization": "Bearer " + self.access_token "Authorization": "Bearer " + self.access_token
} }
params = urllib.urlencode({ params = urlencode({
"instrument" : instrument, "instrument" : instrument,
"units" : event.units, "units" : event.units,
"type" : event.order_type, "type" : event.order_type,
@@ -59,5 +69,5 @@ class OANDAExecutionHandler(ExecutionHandler):
params, headers params, headers
) )
response = self.conn.getresponse().read() response = self.conn.getresponse().read()
print response print(response)
+6 -3
View File
@@ -1,3 +1,5 @@
from __future__ import print_function
from copy import deepcopy from copy import deepcopy
from decimal import Decimal, getcontext, ROUND_HALF_DOWN from decimal import Decimal, getcontext, ROUND_HALF_DOWN
import os import os
@@ -73,7 +75,7 @@ class Portfolio(object):
out_file = os.path.join(OUTPUT_RESULTS_DIR, filename) out_file = os.path.join(OUTPUT_RESULTS_DIR, filename)
df_equity = pd.DataFrame.from_records(self.equity, index='time') df_equity = pd.DataFrame.from_records(self.equity, index='time')
df_equity.to_csv(out_file) df_equity.to_csv(out_file)
print "Simulation complete and results exported to %s" % filename print("Simulation complete and results exported to %s" % filename)
def execute_signal(self, signal_event): def execute_signal(self, signal_event):
side = signal_event.side side = signal_event.side
@@ -123,5 +125,6 @@ class Portfolio(object):
order = OrderEvent(currency_pair, units, "market", side) order = OrderEvent(currency_pair, units, "market", side)
self.events.put(order) self.events.put(order)
print "Balance: %0.2f" % self.balance print("Balance: %0.2f" % self.balance)
self.append_equity_row(time, self.balance) self.append_equity_row(time, self.balance)
+4 -2
View File
@@ -92,7 +92,8 @@ class Position(object):
self.update_position_price() self.update_position_price()
# Calculate PnL # Calculate PnL
pnl = self.calculate_pips() * qh_close * dec_units pnl = self.calculate_pips() * qh_close * dec_units
return pnl.quantize(Decimal("0.01", ROUND_HALF_DOWN)) getcontext().rounding = ROUND_HALF_DOWN
return pnl.quantize(Decimal("0.01"))
def close_position(self): def close_position(self):
ticker_cp = self.ticker.prices[self.currency_pair] ticker_cp = self.ticker.prices[self.currency_pair]
@@ -106,4 +107,5 @@ class Position(object):
self.update_position_price() self.update_position_price()
# Calculate PnL # Calculate PnL
pnl = self.calculate_pips() * qh_close * self.units pnl = self.calculate_pips() * qh_close * self.units
return pnl.quantize(Decimal("0.01", ROUND_HALF_DOWN)) getcontext().rounding = ROUND_HALF_DOWN
return pnl.quantize(Decimal("0.01"))
+1 -5
View File
@@ -1,4 +1,4 @@
from decimal import Decimal, getcontext from decimal import Decimal
import unittest import unittest
from position import Position from position import Position
@@ -28,7 +28,6 @@ class TestLongGBPUSDPosition(unittest.TestCase):
denominated currency of GBP, using 2,000 units of GBP/USD. denominated currency of GBP, using 2,000 units of GBP/USD.
""" """
def setUp(self): def setUp(self):
getcontext.prec = 2
home_currency = "GBP" home_currency = "GBP"
position_type = "long" position_type = "long"
currency_pair = "GBPUSD" currency_pair = "GBPUSD"
@@ -78,7 +77,6 @@ class TestShortGBPUSDPosition(unittest.TestCase):
denominated currency of GBP, using 2,000 units of GBP/USD. denominated currency of GBP, using 2,000 units of GBP/USD.
""" """
def setUp(self): def setUp(self):
getcontext.prec = 2
home_currency = "GBP" home_currency = "GBP"
position_type = "short" position_type = "short"
currency_pair = "GBPUSD" currency_pair = "GBPUSD"
@@ -132,7 +130,6 @@ class TestLongEURUSDPosition(unittest.TestCase):
denominated currency of GBP, using 2,000 units of EUR/USD. denominated currency of GBP, using 2,000 units of EUR/USD.
""" """
def setUp(self): def setUp(self):
getcontext.prec = 2
home_currency = "GBP" home_currency = "GBP"
position_type = "long" position_type = "long"
currency_pair = "EURUSD" currency_pair = "EURUSD"
@@ -183,7 +180,6 @@ class TestLongEURUSDPosition(unittest.TestCase):
denominated currency of GBP, using 2,000 units of EUR/USD. denominated currency of GBP, using 2,000 units of EUR/USD.
""" """
def setUp(self): def setUp(self):
getcontext.prec = 2
home_currency = "GBP" home_currency = "GBP"
position_type = "short" position_type = "short"
currency_pair = "EURUSD" currency_pair = "EURUSD"
+8 -5
View File
@@ -1,8 +1,11 @@
import copy import copy
import Queue from decimal import Decimal, getcontext
try:
import Queue as queue
except ImportError:
import queue
import threading import threading
import time import time
from decimal import Decimal, getcontext
from qsforex.execution.execution import OANDAExecutionHandler from qsforex.execution.execution import OANDAExecutionHandler
from qsforex.portfolio.portfolio import Portfolio from qsforex.portfolio.portfolio import Portfolio
@@ -22,7 +25,7 @@ def trade(events, strategy, portfolio, execution, heartbeat):
while True: while True:
try: try:
event = events.get(False) event = events.get(False)
except Queue.Empty: except queue.Empty:
pass pass
else: else:
if event is not None: if event is not None:
@@ -40,7 +43,7 @@ if __name__ == "__main__":
getcontext().prec = 2 getcontext().prec = 2
heartbeat = 0.0 # Half a second between polling heartbeat = 0.0 # Half a second between polling
events = Queue.Queue() events = queue.Queue()
equity = settings.EQUITY equity = settings.EQUITY
# Trade "Cable" # Trade "Cable"
@@ -81,4 +84,4 @@ if __name__ == "__main__":
# Start both threads # Start both threads
trade_thread.start() trade_thread.start()
price_thread.start() price_thread.start()