Skip to content

Commit

Permalink
Remove all references in 'working' code to Decimal, replace with flat…
Browse files Browse the repository at this point in the history
… integers
  • Loading branch information
ryankennedyio committed Jun 21, 2016
1 parent 3d4a61e commit 4ee3c07
Show file tree
Hide file tree
Showing 9 changed files with 99 additions and 133 deletions.
5 changes: 2 additions & 3 deletions backtest/backtest.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from __future__ import print_function

from decimal import Decimal
import os, os.path
import pprint
from qstrader.statistics.statistics import Statistics
Expand Down Expand Up @@ -31,7 +30,7 @@ def __init__(
execution_handler,
position_sizer, risk_manager,
statistics,
equity=Decimal("100000.00"),
equity=(100000 * settings.PRICE_MULTIPLIER),
heartbeat=0.0, max_iters=10000000000
):
"""
Expand Down Expand Up @@ -112,4 +111,4 @@ def simulate_trading(self):
print("Sharpe Ratio: %s" % results["sharpe"])
print("Max Drawdown: %s" % results["max_drawdown"])
print("Max Drawdown Pct: %s" % results["max_drawdown_pct"])
self.statistics.plot_results()
# self.statistics.plot_results()
4 changes: 1 addition & 3 deletions examples/test_mac_backtest.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from decimal import Decimal

from qstrader.backtest.backtest import Backtest
from qstrader.execution_handler.execution_handler import IBSimulatedExecutionHandler
from qstrader.portfolio_handler.portfolio_handler import PortfolioHandler
Expand All @@ -22,7 +20,7 @@
# Set up variables needed for backtest
events_queue = queue.Queue()
csv_dir = settings.CSV_DATA_DIR
initial_equity = Decimal("500000.00")
initial_equity = 500000 * settings.PRICE_MULTIPLIER
heartbeat = 0.0
max_iters = 10000000000

Expand Down
4 changes: 1 addition & 3 deletions examples/test_sp500tr_buy_and_hold_backtest.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from decimal import Decimal

from qstrader.backtest.backtest import Backtest
from qstrader.execution_handler.execution_handler import IBSimulatedExecutionHandler
from qstrader.portfolio_handler.portfolio_handler import PortfolioHandler
Expand All @@ -21,7 +19,7 @@
# Set up variables needed for backtest
events_queue = queue.Queue()
csv_dir = settings.CSV_DATA_DIR
initial_equity = Decimal("500000.00")
initial_equity = 500000 * settings.PRICE_MULTIPLIER
heartbeat = 0.0
max_iters = 10000000000

Expand Down
4 changes: 1 addition & 3 deletions examples/test_strategy_backtest.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from decimal import Decimal

from qstrader.backtest.backtest import Backtest
from qstrader.execution_handler.execution_handler import IBSimulatedExecutionHandler
from qstrader.portfolio_handler.portfolio_handler import PortfolioHandler
Expand All @@ -21,7 +19,7 @@
# Set up variables needed for backtest
events_queue = queue.Queue()
csv_dir = settings.CSV_DATA_DIR
initial_equity = Decimal("500000.00")
initial_equity = 500000 * settings.PRICE_MULTIPLIER
heartbeat = 0.0
max_iters = 10000000000

Expand Down
18 changes: 13 additions & 5 deletions execution_handler/execution_handler.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import datetime
from decimal import Decimal
try:
import Queue as queue
except ImportError:
Expand All @@ -9,6 +8,15 @@

from qstrader.event.event import FillEvent, OrderEvent

try:
from qstrader import settings
except ImportError:
print(
"Could not import settings.py. Have you copied " \
"settings.py.example to settings.py and configured " \
"your QSTrader settings?"
)


class ExecutionHandler(object):
"""
Expand Down Expand Up @@ -71,7 +79,7 @@ def calculate_ib_commission(self):
a transaction. At this stage, simply add in $1.00
for transaction costs, irrespective of lot size.
"""
return Decimal("1.00")
return 1 * settings.PRICE_MULTIPLIER

def execute_order(self, event):
"""
Expand All @@ -92,12 +100,12 @@ def execute_order(self, event):
if self.price_handler.type == "TICK_HANDLER":
bid, ask = self.price_handler.get_best_bid_ask(ticker)
if event.action == "BOT":
fill_price = Decimal(str(ask))
fill_price = ask
else:
fill_price = Decimal(str(bid))
fill_price = bid
else:
close_price = self.price_handler.get_last_close(ticker)
fill_price = Decimal(str(close_price))
fill_price = close_price

# Set a dummy exchange and calculate trade commission
exchange = "ARCA"
Expand Down
23 changes: 11 additions & 12 deletions portfolio/portfolio.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from decimal import Decimal
from qstrader.position.position import Position


Expand Down Expand Up @@ -27,8 +26,8 @@ def _reset_values(self):
"""
self.cur_cash = self.init_cash
self.equity = self.cur_cash
self.unrealised_pnl = Decimal('0.00')
self.realised_pnl = Decimal('0.00')
self.unrealised_pnl = 0
self.realised_pnl = 0

def _update_portfolio(self):
"""
Expand Down Expand Up @@ -90,7 +89,7 @@ def _add_position(
)

def _modify_position(
self, action, ticker,
self, action, ticker,
quantity, price, commission
):
"""
Expand Down Expand Up @@ -122,28 +121,28 @@ def _modify_position(
)

def transact_position(
self, action, ticker,
self, action, ticker,
quantity, price, commission
):
"""
Handles any new position or modification to
Handles any new position or modification to
a current position, by calling the respective
_add_position and _modify_position methods.
_add_position and _modify_position methods.
Hence, this single method will be called by the
Hence, this single method will be called by the
PortfolioHandler to update the Portfolio itself.
"""
if ticker not in self.positions:
self._add_position(
action, ticker, quantity,
action, ticker, quantity,
price, commission
)
else:
self._modify_position(
action, ticker, quantity,
action, ticker, quantity,
price, commission
)

def create_portfolio_state_dict(self):
"""
Creates a dictionary containing the best estimated
Expand All @@ -158,4 +157,4 @@ def create_portfolio_state_dict(self):
}
for ticker in self.positions:
state_dict[ticker] = self.positions[ticker].market_value
return state_dict
return state_dict
103 changes: 32 additions & 71 deletions position/position.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
from decimal import Decimal


TWOPLACES = Decimal("0.01")
FIVEPLACES = Decimal("0.00001")

from qstrader import settings

class Position(object):
def __init__(
Expand All @@ -25,15 +20,15 @@ def __init__(
self.init_price = init_price
self.init_commission = init_commission

self.realised_pnl = Decimal("0.00")
self.unrealised_pnl = Decimal("0.00")
self.realised_pnl = 0
self.unrealised_pnl = 0

self.buys = Decimal("0")
self.sells = Decimal("0")
self.avg_bot = Decimal("0.00")
self.avg_sld = Decimal("0.00")
self.total_bot = Decimal("0.00")
self.total_sld = Decimal("0.00")
self.buys = 0
self.sells = 0
self.avg_bot = 0
self.avg_sld = 0
self.total_bot = 0
self.total_sld = 0
self.total_commission = init_commission

self._calculate_initial_value()
Expand All @@ -50,27 +45,19 @@ def _calculate_initial_value(self):

if self.action == "BOT":
self.buys = self.quantity
self.avg_bot = self.init_price.quantize(FIVEPLACES)
self.total_bot = (self.buys * self.avg_bot).quantize(TWOPLACES)
self.avg_price = (
(self.init_price * self.quantity + self.init_commission)/self.quantity
).quantize(FIVEPLACES)
self.cost_basis = (
self.quantity * self.avg_price
).quantize(TWOPLACES)
self.avg_bot = self.init_price
self.total_bot = self.buys * self.avg_bot
self.avg_price = (self.init_price * self.quantity + self.init_commission)/self.quantity
self.cost_basis = self.quantity * self.avg_price
else: # action == "SLD"
self.sells = self.quantity
self.avg_sld = self.init_price.quantize(FIVEPLACES)
self.total_sld = (self.sells * self.avg_sld).quantize(TWOPLACES)
self.avg_price = (
(self.init_price * self.quantity - self.init_commission)/self.quantity
).quantize(FIVEPLACES)
self.cost_basis = (
-self.quantity * self.avg_price
).quantize(TWOPLACES)
self.avg_sld = self.init_price
self.total_sld = self.sells * self.avg_sld
self.avg_price = (self.init_price * self.quantity - self.init_commission)/self.quantity
self.cost_basis = -self.quantity * self.avg_price
self.net = self.buys - self.sells
self.net_total = (self.total_sld - self.total_bot).quantize(TWOPLACES)
self.net_incl_comm = (self.net_total - self.init_commission).quantize(TWOPLACES)
self.net_total = self.total_sld - self.total_bot
self.net_incl_comm = self.net_total - self.init_commission

def update_market_value(self, bid, ask):
"""
Expand All @@ -84,16 +71,10 @@ def update_market_value(self, bid, ask):
allows calculation of the unrealised and realised profit
and loss of any transactions.
"""
midpoint = (bid+ask)/Decimal("2.0")
self.market_value = (
self.quantity * midpoint
).quantize(TWOPLACES)
self.unrealised_pnl = (
self.market_value - self.cost_basis
).quantize(TWOPLACES)
self.realised_pnl = (
self.market_value + self.net_incl_comm
)
midpoint = (bid+ask)/2
self.market_value = self.quantity * midpoint
self.unrealised_pnl = self.market_value - self.cost_basis
self.realised_pnl = self.market_value + self.net_incl_comm

def transact_shares(self, action, quantity, price, commission):
"""
Expand All @@ -111,45 +92,25 @@ def transact_shares(self, action, quantity, price, commission):

# Adjust total bought and sold
if action == "BOT":
self.avg_bot = (
(self.avg_bot*self.buys + price*quantity)/(self.buys + quantity)
).quantize(FIVEPLACES)
self.avg_bot = (self.avg_bot*self.buys + price*quantity)/(self.buys + quantity)
if self.action != "SLD":
self.avg_price = (
(
self.avg_price*self.buys +
price*quantity+commission
)/(self.buys + quantity)
).quantize(FIVEPLACES)
self.avg_price = (self.avg_price*self.buys + price*quantity+commission)/(self.buys + quantity)
self.buys += quantity
self.total_bot = (self.buys * self.avg_bot).quantize(TWOPLACES)
self.total_bot = self.buys * self.avg_bot

# action == "SLD"
else:
self.avg_sld = (
(self.avg_sld*self.sells + price*quantity)/(self.sells + quantity)
).quantize(FIVEPLACES)
self.avg_sld = (self.avg_sld*self.sells + price*quantity)/(self.sells + quantity)
if self.action != "BOT":
self.avg_price = (
(
self.avg_price*self.sells +
price*quantity-commission
)/(self.sells + quantity)
).quantize(FIVEPLACES)
self.avg_price =(self.avg_price*self.sells + price*quantity-commission)/(self.sells + quantity)
self.sells += quantity
self.total_sld = (self.sells * self.avg_sld).quantize(TWOPLACES)
self.total_sld = self.sells * self.avg_sld

# Adjust net values, including commissions
self.net = self.buys - self.sells
self.quantity = self.net
self.net_total = (
self.total_sld - self.total_bot
).quantize(TWOPLACES)
self.net_incl_comm = (
self.net_total - self.total_commission
).quantize(TWOPLACES)
self.net_total = self.total_sld - self.total_bot
self.net_incl_comm = self.net_total - self.total_commission

# Adjust average price and cost basis
self.cost_basis = (
self.quantity * self.avg_price
).quantize(TWOPLACES)
self.cost_basis = self.quantity * self.avg_price
Loading

0 comments on commit 4ee3c07

Please sign in to comment.