First commit

This commit is contained in:
Michael Halls-Moore
2015-01-27 18:29:27 +00:00
commit e223aa5751
6 changed files with 316 additions and 0 deletions
+28
View File
@@ -0,0 +1,28 @@
*~
*.py[co]
# Packages
*.egg
*.egg-info
dist
build
eggs
parts
bin
var
sdist
develop-eggs
.installed.cfg
# Installer logs
pip-log.txt
# Unit test / coverage reports
.coverage
.tox
#Translations
*.mo
#Mr Developer
.mr.developer.cfg
View File
+129
View File
@@ -0,0 +1,129 @@
from copy import deepcopy
from position import Position
class Portfolio(object):
def __init__(
self, ticker, base="GBP", leverage=20,
equity=100000.0, risk_per_trade=0.02
):
self.ticker = ticker
self.base = base
self.leverage = leverage
self.equity = equity
self.balance = deepcopy(self.equity)
self.risk_per_trade = risk_per_trade
self.trade_units = self.calc_risk_position_size()
self.positions = {}
def calc_risk_position_size(self):
return self.equity * self.risk_per_trade
def add_new_position(
self, side, market, units, exposure,
add_price, remove_price
):
ps = Position(
side, market, units, exposure,
add_price, remove_price
)
self.positions[market] = ps
def add_position_units(
self, market, units, exposure,
add_price, remove_price
):
if market not in self.positions:
return False
else:
ps = self.positions[market]
new_total_units = ps.units + units
new_total_cost = ps.avg_price*ps.units + add_price*units
ps.exposure += exposure
ps.avg_price = new_total_cost/new_total_units
ps.units = new_total_units
ps.update_position_price(remove_price)
return True
def remove_position_units(
self, market, units, remove_price
):
if market not in self.positions:
return False
else:
ps = self.positions[market]
ps.units -= units
ps.exposure -= float(units)
ps.update_position_price(self, remove_price)
pnl = ps.profit_base
self.balance += pnl
return True
def close_position(
self, market, remove_price
):
if market not in self.positions:
return False
else:
ps = self.positions[market]
ps.update_position_price(self, remove_price)
pnl = ps.profit_base
self.balance += pnl
del[self.positions[market]]
return True
def execute_signal(self, signal_event):
side = signal_event.side
market = signal_event.market
units = self.risk_per_trade
# Check side for correct bid/ask prices
if side == "LONG":
add_price = self.ticker.cur_ask
remove_price = self.ticker.cur_bid
else:
add_price = self.ticker.cur_bid
remove_price = self.ticker.cur_ask
exposure = float(units)
# If there is no position, create one
if market not in self.positions:
self.add_new_position(
side, market, units, exposure,
add_price, remove_price
)
# If a position exists add or remove units
else:
# Check if the sides equal
if side == ps[market].side:
# Add to the position
add_position_units(
market, units, exposure,
add_price, remove_price
)
else:
# Check if the units close out the position
if units == ps.units:
# Close the position
self.close_position(market, remove_price)
elif units < ps.units:
# Remove from the position
self.remove_position_units(
market, units, remove_price
)
else: # units > ps.units
# Close the position and add a new one with
# additional units of opposite side
new_units = units - ps.units
self.close_position(market, remove_price)
if side == "LONG":
new_side = "SHORT"
else:
new_side = "LONG"
new_exposure = float(units)
self.add_new_position(
new_side, market, new_units,
new_exposure, add_price, remove_price
)
+68
View File
@@ -0,0 +1,68 @@
import unittest
#from position import Position
from portfolio import Portfolio
class TestPortfolio(unittest.TestCase):
def setUp(self):
base = "GBP"
leverage = 20
equity = 100000.0
risk_per_trade = 0.02
ticker = {}
self.port = Portfolio(
ticker, base=base, leverage=leverage,
equity=equity, risk_per_trade=risk_per_trade
)
def test_add_position(self):
side = "LONG"
market = "GBP/USD"
units = 2000
exposure = float(units)
add_price = 1.51819
remove_price = 1.51770
self.port.add_new_position(
side, market, units, exposure,
add_price, remove_price
)
ps = self.port.positions[market]
self.assertEquals(ps.side, side)
self.assertEquals(ps.market, market)
self.assertEquals(ps.units, units)
self.assertEquals(ps.exposure, exposure)
self.assertEquals(ps.avg_price, add_price)
self.assertEquals(ps.cur_price, remove_price)
def test_add_position_units(self):
side = "LONG"
units = 2000
exposure = float(units)
add_price = 1.51928
remove_price = 1.51878
# Test for no position
market = "EUR/USD"
apu = self.port.add_position_units(
market, units, exposure,
add_price, remove_price
)
self.assertFalse(apu)
# Test for real position
market = "GBP/USD"
apu = self.port.add_position_units(
market, units, exposure,
add_price, remove_price
)
self.assertTrue(apu)
ps = self.port.positions[market]
self.assertAlmostEqual(ps.avg_price, 1.518735)
if __name__ == "__main__":
unittest.main()
+32
View File
@@ -0,0 +1,32 @@
class Position(object):
def __init__(
self, side, market, units,
exposure, avg_price, cur_price
):
self.side = side
self.market = market
self.units = units
self.exposure = exposure
self.avg_price = avg_price
self.cur_price = cur_price
self.profit_base = self.calculate_profit_base()
self.profit_perc = self.calculate_profit_perc()
def calculate_pips(self):
mult = 1.0
if self.side == "SHORT":
mult = -1.0
return mult * (self.cur_price - self.avg_price)
def calculate_profit_base(self):
pips = self.calculate_pips()
return pips * self.exposure / self.cur_price
def calculate_profit_perc(self):
return self.profit_base / self.exposure * 100.0
def update_position_price(self, cur_price):
self.cur_price = cur_price
self.profit_base = self.calculate_profit_base()
self.profit_perc = self.calculate_profit_perc()
+59
View File
@@ -0,0 +1,59 @@
import unittest
from position import Position
class TestLongGBPUSDPosition(unittest.TestCase):
def setUp(self):
side = "LONG"
market = "GBP/USD"
units = 2000
exposure = 2000.0
avg_price = 1.51819
cur_price = 1.51770
self.position = Position(
side, market, units, exposure,
avg_price, cur_price
)
def test_calculate_pips(self):
pos_pips = self.position.calculate_pips()
self.assertAlmostEqual(pos_pips, -0.00049)
def test_calculate_profit_base(self):
profit_base = self.position.calculate_profit_base()
self.assertAlmostEqual(profit_base, -0.6457139)
def test_calculate_profit_perc(self):
profit_perc = self.position.calculate_profit_perc()
self.assertAlmostEqual(profit_perc, -0.032285695)
class TestShortGBPUSDPosition(unittest.TestCase):
def setUp(self):
side = "SHORT"
market = "GBP/USD"
units = 2000
exposure = 2000.0
avg_price = 1.51819
cur_price = 1.51770
self.position = Position(
side, market, units, exposure,
avg_price, cur_price
)
def test_calculate_pips(self):
pos_pips = self.position.calculate_pips()
self.assertAlmostEqual(pos_pips, 0.00049)
def test_calculate_profit_base(self):
profit_base = self.position.calculate_profit_base()
self.assertAlmostEqual(profit_base, 0.6457139)
def test_calculate_profit_perc(self):
profit_perc = self.position.calculate_profit_perc()
self.assertAlmostEqual(profit_perc, 0.032285695)
if __name__ == "__main__":
unittest.main()