Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop' into dev/travis-setup
Browse files Browse the repository at this point in the history
  • Loading branch information
edouardpoitras committed Oct 1, 2015
2 parents d71a587 + acb86a3 commit 8c3d8bf
Show file tree
Hide file tree
Showing 8 changed files with 169 additions and 71 deletions.
10 changes: 5 additions & 5 deletions examples/neural_network.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,18 +167,18 @@ And there you have it! You can clearly see what the 'TestNN' predictions where

Let's create our trading criteria, starting with some entry criteria. We want to check if the stock's current price is 'below' the threshold_below value - this will indicate that the neural network is predicting that the stock price will go up by more than $5 in our prediction window.

enter_crit_long = criteria.Position(googl.close, 'below', threshold_below.value)
enter_crit_long = criteria.Below(googl.close, threshold_below.value)

We also want to check if the current stock price is 'above' the threshold_above value, which would indicate that the neural network is predicting that the stock price will go down by more than $5 in our prediction window.

enter_crit_short = criteria.Position(symbol.close, 'above', threshold_above.value)
enter_crit_short = criteria.Above(symbol.close, threshold_above.value)

As for our exit criteria, we only have one, and it would probably be wise if it matched our neural network training parameters from earlier. We had trained the network to predict the price 1 day into the future. Therefore, we should have an exit criteria that says, "When we've been in the market for 1 day(s), exit".

exit_crit_long = criteria.TimeSinceAction(googl, Long(), 1)
exit_crit_short = criteria.TimeSinceAction(googl, Short(), 1)
exit_crit_long = criteria.BarsSinceLong(googl, 1)
exit_crit_short = criteria.BarsSinceShort(googl, 1)

Pretty straightforward. The TimeSinceAction criteria takes a stock, an action (such as Long(), Short(), LongExit(), ShortExit()), and a number of days/hours/minutes/etc. The criteria will return true if the action specified has happened for the stock in the past X days/hours/minutes/etc - In this case, if we have Long'ed and/or Short'ed googl exactly 1 days ago.
Pretty straightforward. The BarsSinceLong/BarsSinceShort/BarsSinceLongExit/BarsSinceShortExit criteria takes a stock and a number of bars. The criteria will return true if the specific action has happened for the stock in the past X bars - In this case, if we have Long'ed and/or Short'ed googl exactly 1 day ago.

We could have just as easily used +/- $5 from our stock price instead of the neural network prediction price. Then we could have checked if the neural network price fell outside that range to trade accordingly.

Expand Down
8 changes: 4 additions & 4 deletions examples/neural_network.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@
test_dataset.add_technical_indicator(threshold_below)
# Criteria
# Current price is below the threshold of our neural network's prediction price
enter_crit_long = criteria.Position(symbol.close, 'below', threshold_below.value)
enter_crit_long = criteria.Below(symbol.close, threshold_below.value)
# Current price is above the threshold of our neural network's prediction price
enter_crit_short = criteria.Position(symbol.close, 'above', threshold_above.value)
enter_crit_short = criteria.Above(symbol.close, threshold_above.value)
# Exit after 1 day - as per the network's parameters
exit_crit_long = criteria.TimeSinceAction(symbol, Long(), 1)
exit_crit_short = criteria.TimeSinceAction(symbol, Short(), 1)
exit_crit_long = criteria.BarsSinceLong(symbol, 1)
exit_crit_short = criteria.BarsSinceShort(symbol, 1)
# Criteria Groups
enter_crit_group1 = criteria_group.CriteriaGroup([enter_crit_long], Long(), symbol)
enter_crit_group2 = criteria_group.CriteriaGroup([enter_crit_short], Short(), symbol)
Expand Down
12 changes: 6 additions & 6 deletions examples/random_forest.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ Typically, this is the part where I would create the testing data set, but we've

Our random forest technical indicator will spit out prediction prices, but we still need a threshold to determine whether or not we want to enter the trade. Let's define a technical indicator that is $5 higher than the ensemble's prediction, and one that is $5 lower.

_Note that we could have also simply used a Position criteria on the ensemble price and skipped the threshold step entirely._
_Note that we could have also simply used a Above and Below criteria on the ensemble price and skipped the threshold step entirely._

threshold_above = technical_indicator.Addition(random_forest.value, 5)
test_dataset.add_technical_indicator(threshold_above)
Expand Down Expand Up @@ -133,18 +133,18 @@ Click [here](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFr

Let's create our trading criteria, starting with some entry criteria. We want to check if the stock's current price is 'below' the threshold_below value - this will indicate that the random forest ensemble is predicting that the stock price will go up by more than $5 in our prediction window.

enter_crit_long = criteria.Position(symbol.close, 'below', threshold_below.value)
enter_crit_long = criteria.Below(symbol.close, threshold_below.value)

We also want to check if the current stock price is 'above' the threshold_above value, which would indicate that the random forest ensemble is predicting that the stock price will go down by more than $5 in our prediction window.

enter_crit_short = criteria.Position(symbol.close, 'above', threshold_above.value)
enter_crit_short = criteria.Above(symbol.close, threshold_above.value)

As for our exit criteria, we only have one, and it would probably be wise if it matched our ensemble fitting parameters from earlier. We fit the model to predict the price 5 days into the future. Therefore, we should have an exit criteria that says, "When we've been in the market for 5 days, exit".

exit_crit_long = criteria.TimeSinceAction(symbol, Long(), 5)
exit_crit_short = criteria.TimeSinceAction(symbol, Short(), 5)
exit_crit_long = criteria.BarsSinceLong(symbol, 5)
exit_crit_short = criteria.BarsSinceShort(symbol, 5)

Pretty straightforward. The TimeSinceAction criteria takes a stock, an action (such as Long(), Short(), LongExit(), ShortExit()), and a number of days/hours/minutes/etc. The criteria will return true if the action specified has happened for the stock in the past X days/hours/minutes/etc - In this case, if we have Long'ed and/or Short'ed GOOGL exactly 5 days ago.
Pretty straightforward. The BarsSinceLong/BarsSinceShort/BarsSinceLongExit/BarsSinceShortExit criteria takes a stock and a number of bars. The criteria will return true if the specific action has happened for the stock in the past X bars - In this case, if we have Long'ed and/or Short'ed GOOGL exactly 5 days ago.

We could have just as easily used +/- $5 from our stock price instead of the random forest prediction price. Then we could have checked if the random forest price fell outside that range to trade accordingly.

Expand Down
8 changes: 4 additions & 4 deletions examples/random_forest.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@
test_dataset.add_technical_indicator(threshold_below)
# Criteria
# Current price is below the threshold of our random forest's prediction price
enter_crit_long = criteria.Position(symbol.close, 'below', threshold_below.value)
enter_crit_long = criteria.Below(symbol.close, threshold_below.value)
# Current price is above the threshold of our random forest's prediction price
enter_crit_short = criteria.Position(symbol.close, 'above', threshold_above.value)
enter_crit_short = criteria.Above(symbol.close, threshold_above.value)
# Exit after 5 days - as per the random forest's build parameters
exit_crit_long = criteria.TimeSinceAction(symbol, Long(), 5)
exit_crit_short = criteria.TimeSinceAction(symbol, Short(), 5)
exit_crit_long = criteria.BarsSinceLong(symbol, 5)
exit_crit_short = criteria.BarsSinceShort(symbol, 5)
# Criteria Groups
enter_crit_group1 = criteria_group.CriteriaGroup([enter_crit_long], Long(), symbol)
enter_crit_group2 = criteria_group.CriteriaGroup([enter_crit_short], Short(), symbol)
Expand Down
4 changes: 2 additions & 2 deletions nowtrade/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
# Criteria module
#LOGGING_Position_CONSOLE = logging.DEBUG
#LOGGING_Position_FILE = logging.DEBUG
#LOGGING_TimeSinceAction_CONSOLE = logging.DEBUG
#LOGGING_TimeSinceAction_FILE = logging.DEBUG
#LOGGING_BarsSinceLong_CONSOLE = logging.DEBUG
#LOGGING_BarsSinceLong_FILE = logging.DEBUG

# Criteria Group module
#LOGGING_CriteriaGroup_CONSOLE = logging.DEBUG
Expand Down
92 changes: 89 additions & 3 deletions nowtrade/criteria.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import numpy as np
import pandas as pd
from nowtrade import logger
from nowtrade import action

class Criteria(object):
"""
Expand All @@ -14,18 +15,18 @@ def __init__(self):
# Some TIs don't require the entire data_frame history.
self.num_bars_required = None # Requires all history by default

class TimeSinceAction(Criteria):
class BarsSinceAction(Criteria):
def __init__(self, symbol, action, periods, condition=None):
Criteria.__init__(self)
self.symbol = str(symbol)
self.action = action.raw()
self.periods = periods
self.condition = str(condition).upper()
self.num_bars_required = self.periods + 1
self.label = 'TimeSinceAction_%s_%s_%s_%s' %(symbol, action, periods, condition)
self.label = 'BarsSinceAction_%s_%s_%s_%s' %(symbol, action, periods, condition)
self.logger.info('Initialized - %s' %self)
def __str__(self):
return 'TimeSinceAction(symbol=%s, action=%s, periods=%s, condition=%s)' %(self.symbol, self.action, self.periods, self.condition)
return 'BarsSinceAction(symbol=%s, action=%s, periods=%s, condition=%s)' %(self.symbol, self.action, self.periods, self.condition)
def __repr__(self): return self.label
def apply(self, data_frame):
if self.condition == 'OVER':
Expand All @@ -40,6 +41,31 @@ def apply(self, data_frame):
return self.action == data_frame['ACTIONS_%s' %self.symbol][-1-self.periods]
return False

class BarsSinceLong(BarsSinceAction):
def __init__(self, symbol, periods, condition=None):
BarsSinceAction.__init__(self, symbol, action.Long(), periods, condition)
self.label = 'BarsSinceLong_%s_%s_%s' %(symbol, periods, condition)
def __str__(self):
return 'BarsSinceLong(symbol=%s, periods=%s, condition=%s)' %(self.symbol, self.periods, self.condition)
class BarsSinceShort(BarsSinceAction):
def __init__(self, symbol, periods, condition=None):
BarsSinceAction.__init__(self, symbol, action.Short(), periods, condition)
self.label = 'BarsSinceShort_%s_%s_%s' %(symbol, periods, condition)
def __str__(self):
return 'BarsSinceShort(symbol=%s, periods=%s, condition=%s)' %(self.symbol, self.periods, self.condition)
class BarsSinceLongExit(BarsSinceAction):
def __init__(self, symbol, periods, condition=None):
BarsSinceAction.__init__(self, symbol, action.LongExit(), periods, condition)
self.label = 'BarsSinceLongExit_%s_%s_%s' %(symbol, periods, condition)
def __str__(self):
return 'BarsSinceLongExit(symbol=%s, periods=%s, condition=%s)' %(self.symbol, self.periods, self.condition)
class BarsSinceShortExit(BarsSinceAction):
def __init__(self, symbol, periods, condition=None):
BarsSinceAction.__init__(self, symbol, action.ShortExit(), periods, condition)
self.label = 'BarsSinceShortExit_%s_%s_%s' %(symbol, periods, condition)
def __str__(self):
return 'BarsSinceShortExit(symbol=%s, periods=%s, condition=%s)' %(self.symbol, self.periods, self.condition)

class InMarket(Criteria):
"""
Looks one period behind the current period because it expects the last
Expand Down Expand Up @@ -282,6 +308,66 @@ def apply(self, data_frame):
else: results = data_frame[self.param1] == data_frame[self.param2]
return results.iloc[-1]

class Above(Criteria):
def __init__(self, param1, param2, lookback=1):
Criteria.__init__(self)
self.param1 = param1 # Technical indicator label
self.param2 = param2 # Technical indicator label or int or long or float
self.lookback = lookback
self.label = 'Above_%s_%s_%s' %(param1, param2, lookback)
self.num_bars_required = lookback
self.logger.info('Initialized - %s' %self)
def __str__(self):
return 'Above(param1=%s, param2=%s, lookback=%s)' %(self.param1, self.param2, self.lookback)
def __repr__(self): return self.label
def apply(self, data_frame):
if len(data_frame) < self.lookback: return False
# Second value is not a technical indicator, simply a number to compare
if isinstance(self.param2, (int, long, float)):
print 'comparing %s with %s' %(data_frame[self.param1][-self.lookback], self.param2)
return data_frame[self.param1][-self.lookback] > self.param2
else: return data_frame[self.param1][-self.lookback] > data_frame[self.param2][-self.lookback]

class Below(Criteria):
def __init__(self, param1, param2, lookback=1):
Criteria.__init__(self)
self.param1 = param1 # Technical indicator label
self.param2 = param2 # Technical indicator label or int or long or float
self.lookback = lookback
self.label = 'Below_%s_%s_%s' %(param1, param2, lookback)
self.num_bars_required = lookback
self.logger.info('Initialized - %s' %self)
def __str__(self):
return 'Below(param1=%s, param2=%s, lookback=%s)' %(self.param1, self.param2, self.lookback)
def __repr__(self): return self.label
def apply(self, data_frame):
if len(data_frame) < self.lookback: return False
# Second value is not a technical indicator, simply a number to compare
if isinstance(self.param2, (int, long, float)):
return data_frame[self.param1][-self.lookback] < self.param2
else: return data_frame[self.param1][-self.lookback] < data_frame[self.param2][-self.lookback]

class Equals(Criteria):
def __init__(self, param1, param2, lookback=1):
Criteria.__init__(self)
self.param1 = param1 # Technical indicator label
self.param2 = param2 # Technical indicator label or int or long or float
self.lookback = lookback
self.label = 'Equals_%s_%s_%s' %(param1, param2, lookback)
self.num_bars_required = lookback
self.logger.info('Initialized - %s' %self)
def __str__(self):
return 'Equals(param1=%s, param2=%s, lookback=%s)' %(self.param1, self.param2, self.lookback)
def __repr__(self): return self.label
def apply(self, data_frame):
if len(data_frame) < self.lookback: return False
# Second value is not a technical indicator, simply a number to compare
if isinstance(self.param2, (int, long, float)):
print 'comparing %s and %s' %(data_frame[self.param1][-self.lookback], self.param2)
return data_frame[self.param1][-self.lookback] == self.param2
else: return data_frame[self.param1][-self.lookback] == data_frame[self.param2][-self.lookback]
Equal = Equals

class InRange(Criteria):
"""
Determines if a technical indicator is in between two values.
Expand Down

0 comments on commit 8c3d8bf

Please sign in to comment.