![]() | ![]() |
# of Entries...........8 # of Exits.............9 WinRatio..............77.78% Portfolio's ROI.......+3.44% Market's ROI..........-1.35%
Later Trades,
MT
The critical ingredient is a maverick mind. Focus on trading vehicles, strategies and time horizons that suit your personality. In a nutshell, it all comes down to: Do your own thing (independence); and do the right thing (discipline). -- Gil Blake
![]() |
![]() |
# of Entries...........7 # of Exits.............6 WinRatio..............66.66% Portfolio's ROI.......+0.89% Market's ROI..........+2.85%
![]() |
![]() |
# of Entries...........8 # of Exits............10 WinRatio..............70.00% Portfolio's ROI.......+3.38% Market's ROI..........-0.10%
![]() | ![]() |
# of Entries...........8 # of Exits.............7 WinRatio..............80.00% Portfolio's ROI........5.82% Market's ROI...........3.20%
It's not about finding a system your comfortable with. It's about getting comfortable with a winning system.
![]() |
![]() |
# of Entries.......8 # of Exits.........7
![]() |
![]() |
import heapq
class MaxItems(object):
"""
Caches the max X items of whatever you're analyzing and
returns a list containing only those max X values and
associated items.
"""
def __init__(self, size):
self.size = size
self._recs = []
def push(self, value, items):
if len(self._recs) < self.size:
heapq.heappush(self._recs, (value, items))
else:
minitem = heapq.heappushpop(self._recs, (value, items))
def items(self):
return heapq.nlargest(self.size, self._recs)
Example call and results:
pricegains = []
pricegains.append({'symbol':'GOOG', 'gain':234.0})
pricegains.append({'symbol':'YHOO', 'gain':124.0})
pricegains.append({'symbol':'IBM', 'gain':1242.0})
pricegains.append({'symbol':'GE', 'gain':1800.0})
pricegains.append({'symbol':'ENE', 'gain':0.0})
pricegains.append({'symbol':'KREM', 'gain':12.0})
maxitems = MaxItems(3)
for row in pricegains:
maxitems.push(row['gain'], row)
print maxitems.items()
----------------------------------------------------------
Results of call:
(1800.0, {'symbol': 'GE', 'gain': 1800.0})
(1242.0, {'symbol': 'IBM', 'gain': 1242.0})
(234.0, {'symbol': 'GOOG', 'gain': 234.0})
The heapq module works nicely in accomplishing the task. What's ironic is Python's heapq module implements the min-heap algorithm which works out nicely and efficiently in determining the maximum values over a list. But, does not work out so efficiently for determining the minimum values over a list.
import bisect
class MaxItems2(object):
"""
Caches the max X items of whatever you're analyzing and
returns a list containing only those max X values and
associated items.
"""
def __init__(self, size):
self.size = size
self._recs = []
def push(self, value, items):
if len(self._recs) < self.size:
bisect.insort(self._recs, (value, items))
elif bisect.bisect(self._recs, (value, items)) > self.size:
bisect.insort(self._recs, (value, items))
minitem = self._recs.pop(0)
def items(self):
return sorted(self._recs, reverse=True)
MaxItems2 takes advantage of the bisect module and while it works great; performance is at a minimum 2x worse on average than using the heapq method.
import random
pricegains = []
maxitems = MaxItems(100)
for x in xrange(500000):
gain = random.uniform(1.0,500.0)
maxitems.push(gain, ('This', 'is', 'Record'))
rows = maxitems.items()
Calling the above code with the wonderful timeit module produced the following results:
![]() |
![]() |
def powersumavg(bar, series, period, pval=None):
"""
Returns the power sum average based on the blog post from
Subliminal Messages. Use the power sum average to help derive the running
variance.
sources: http://subluminal.wordpress.com/2008/07/31/running-standard-deviations/
Keyword arguments:
bar -- current index or location of the value in the series
series -- list or tuple of data to average
period -- number of values to include in average
pval -- previous powersumavg (n - 1) of the series.
"""
if period < 1:
raise ValueError("period must be 1 or greater")
if bar < 0:
bar = 0
if pval == None:
if bar > 0:
raise ValueError("pval of None invalid when bar > 0")
pval = 0.0
newamt = float(series[bar])
if bar < period:
result = pval + (newamt * newamt - pval) / (bar + 1.0)
else:
oldamt = float(series[bar - period])
result = pval + (((newamt * newamt) - (oldamt * oldamt)) / period)
return result
Code for the Running Windowed Variance:
def running_var(bar, series, period, asma, apowsumavg):
"""
Returns the running variance based on a given time period.
sources: http://subluminal.wordpress.com/2008/07/31/running-standard-deviations/
Keyword arguments:
bar -- current index or location of the value in the series
series -- list or tuple of data to average
asma -- current average of the given period
apowsumavg -- current powersumavg of the given period
"""
if period < 1:
raise ValueError("period must be 1 or greater")
if bar <= 0:
return 0.0
if asma == None:
raise ValueError("asma of None invalid when bar > 0")
if apowsumavg == None:
raise ValueError("powsumavg of None invalid when bar > 0")
windowsize = bar + 1.0
if windowsize >= period:
windowsize = period
return (apowsumavg * windowsize - windowsize * asma * asma) / windowsize
Example call and results:
list_of_values = [3, 5, 8, 10, 4, 8, 12, 15, 11, 9]
prev_powersumavg = None
prev_sma = None
prev_sma = None
period = 3
for bar, price in enumerate(list_of_values):
new_sma = running_sma(bar, list_of_values, period, prev_sma)
new_powersumavg = powersumavg(bar, list_of_values, period, prev_powersumavg)
new_var = running_var(bar, list_of_values, period, new_sma, new_powersumavg)
msg = "SMA=%.4f, PSA=%.4f, Var=%.4f" % (new_sma, new_powersumavg, new_var)
print "bar %i: %s" % (bar, msg)
prev_sma = new_sma
prev_powersumavg = new_powersumavg
----------------------------------------------------------
Results of call:
bar 0: SMA=3.0000, PSA=9.0000, Var=0.0000
bar 1: SMA=4.0000, PSA=17.0000, Var=1.0000
bar 2: SMA=5.3333, PSA=32.6667, Var=4.2222
bar 3: SMA=7.6667, PSA=63.0000, Var=4.2222
bar 4: SMA=7.3333, PSA=60.0000, Var=6.2222
bar 5: SMA=7.3333, PSA=60.0000, Var=6.2222
bar 6: SMA=8.0000, PSA=74.6667, Var=10.6667
bar 7: SMA=11.6667, PSA=144.3333, Var=8.2222
bar 8: SMA=12.6667, PSA=163.3333, Var=2.8889
bar 9: SMA=11.6667, PSA=142.3333, Var=6.2222
Of course, as I said in the beginning of this post, just take the square root of this Running Windowed Variance to obtain the Standard Deviation.
![]() |
![]() |
![]() |
![]() |
Jacob: "How's your day going?"
Lewis: "I told you...good day I'm okay, bad day...I'm okay. Stop bugging me on my feelings, their irrelevant."
bar 1: 20 bar 2: 20 + 40 = 60 bar 3: 20 + 40 + 60 = 120 bar 4: 40 + 60 + 80 = 180Or we can apply our formula from above as \( Sum_{today} = 120 + (80 - 20) \)
bar 5: 60 + 80 + 100 = 240Or use formula of \( Sum_{today} = 180 + (100 - 40) \)
bar 6: 80 + 100 + 120 = 300Or use formula of \( Sum_{today} = 240 + (120 - 60) \)
def running_sum(bar, series, period, pval=None):
"""
Returns the running sum of values in a list of tuple - avoids summing
entire series on each call.
Keyword arguments:
bar -- current index or location of the value in the series
series -- list or tuple of data to sum
period -- number of values to include in sum
pval -- previous sum (n - 1) of the series.
"""
if period < 1:
raise ValueError("period must be 1 or greater")
if bar <= 0:
return series[0]
if bar < period:
return pval + series[bar]
return pval + (series[bar] - series[bar - period])
Example call and results:
list_of_values = [20, 40, 60, 80, 100, 120]
prevsum = list_of_values[0] #first sum is the first value in the series.
for bar, price in enumerate(list_of_values):
newsum = running_sum(bar, list_of_values, 3, pval=prevsum)
print "bar %i: %i" % (bar, newsum)
prevsum = newsum
----------------------------------------------------------
bar 0: 20
bar 1: 60
bar 2: 120
bar 3: 180
bar 4: 240
bar 5: 300
![]() |
![]() |

def ema(bar, series, period, prevma, smoothing=None):
'''Returns the Exponential Moving Average of a series.
Keyword arguments:
bar -- currrent index or location of the series
series -- series of values to be averaged
period -- number of values in the series to average
prevma -- previous exponential moving average
smoothing -- smoothing factor to use in the series.
valid values: between 0 & 1.
default: None - which then uses formula = 2.0 / (period + 1.0)
closer to 1 to gives greater weight to recent values - less smooth
closer to 0 gives greater weight to older values -- more smooth
'''
if period < 1:
raise ValueError("period must be 1 or greater")
if smoothing:
if (smoothing < 0) or (smoothing > 1.0):
raise ValueError("smoothing must be between 0 and 1")
else:
smoothing = 2.0 / (period + 1.0)
if bar <= 0:
return series[0]
elif bar < period:
return cumulative_sma(bar, series, prevma)
return prevma + smoothing * (series[bar] - prevma)
def cumulative_sma(bar, series, prevma):
"""
Returns the cumulative or unweighted simple moving average.
Avoids averaging the entire series on each call.
Keyword arguments:
bar -- current index or location of the value in the series
series -- list or tuple of data to average
prevma -- previous average (n - 1) of the series.
"""
if bar <= 0:
return series[0]
else:
return prevma + ((series[bar] - prevma) / (bar + 1.0))
prices = [32.47, 32.70, 32.77, 33.11, 33.25, 33.23, 33.23, 33.0, 33.04, 33.21]
period = 5 #number of bars to average
prevsma = prevema = prices[0] #1st day nothing to average
for bar, close in enumerate(prices):
currentema = ema(bar, prices, period, prevema, smoothing=None)
#running_sma defined in simple moving average blog post
currentsma = running_sma(bar, prices, period, prevsma)
print "Day %02d Value=%.2f %i-bar SMA=%f and EMA=%f" % (bar + 1, close, period, currentsma, currentema)
prevema = currentema
prevsma = currentsma
----------------------------------------------------------
Results of call:
Day 01 Value=32.47 5-day SMA=32.470000 and EMA=32.470000
Day 02 Value=32.70 5-day SMA=32.585000 and EMA=32.585000
Day 03 Value=32.77 5-day SMA=32.646667 and EMA=32.646667
Day 04 Value=33.11 5-day SMA=32.762500 and EMA=32.762500
Day 05 Value=33.25 5-day SMA=32.860000 and EMA=32.860000
Day 06 Value=33.23 5-day SMA=33.012000 and EMA=32.983333
Day 07 Value=33.23 5-day SMA=33.118000 and EMA=33.065556
Day 08 Value=33.00 5-day SMA=33.164000 and EMA=33.043704
Day 09 Value=33.04 5-day SMA=33.150000 and EMA=33.042469
Day 10 Value=33.21 5-day SMA=33.142000 and EMA=33.098313
"Time flies like an arrow; fruit flies like a banana" -- Groucho Marx

def cumulative_sma(bar, series, prevma):
"""
Returns the cumulative or unweighted simple moving average.
Avoids sum of series per call.
Keyword arguments:
bar -- current index or location of the value in the series
series -- list or tuple of data to average
prevma -- previous average (n - 1) of the series.
"""
if bar <= 0:
return series[0]
return prevma + ((series[bar] - prevma) / (bar + 1.0))
def running_sma(bar, series, period, prevma):
"""
Returns the running simple moving average - avoids sum of series per call.
Keyword arguments:
bar -- current index or location of the value in the series
series -- list or tuple of data to average
period -- number of values to include in average
prevma -- previous simple moving average (n - 1) of the series
"""
if period < 1:
raise ValueError("period must be 1 or greater")
if bar <= 0:
return series[0]
elif bar < period:
return cumulative_sma(bar, series, prevma)
return prevma + ((series[bar] - series[bar - period]) / float(period))
And the example call and results:
prices = [10, 15, 25, 18, 13, 16]
prevsma = prices[0] #1st day nothing to average so return itself.
for bar, close in enumerate(prices):
currentsma = running_sma(bar, prices, 3, prevsma)
print "Today's 3-day SMA = %.4f" % currentsma
prevsma = currentsma
------- Results ----------------
Today's 3-day SMA = 10.0000
Today's 3-day SMA = 12.5000
Today's 3-day SMA = 16.6667
Today's 3-day SMA = 19.3333
Today's 3-day SMA = 18.6667
Today's 3-day SMA = 15.6667
| Key Figures | Russell 3000 | IWV |
|---|---|---|
| Total Active Components | 2961 | 1 |
| Total New Listings this period | 0 | 0 |
| Total Inactive this period | 1 | 0 |
| # All-time Closing Highs | 28 (0.19%) | 0 (0.00%) |
| # All-time Closing Lows | 87 (0.59%) | 0 (0.00%) |
| # Higher Closes | 6755 (45.63%) | 2 (40.00%) |
| # Lower Closes | 7775 (52.52%) | 3 (60.00%) |
| Total Gains/Losses | $1059.55 (0.28%) | $0.45 (0.14%) |
| Average True Range | (4.59%) | (2.51%) |
| Key Figures | Russell 3000 | IWV |
|---|---|---|
| Total Active Components | 2961 | 1 |
| Total New Listings this period | 0 | 0 |
| Total Inactive this period | 0 | 0 |
| # All-time Closing Highs | 10 (0.34%) | 0 (0.00%) |
| # All-time Closing Lows | 6 (0.20%) | 0 (0.00%) |
| # Higher Closes | 508 (17.16%) | 0 (0.00%) |
| # Lower Closes | 2402 (81.12%) | 1 (100.00%) |
| Total Gains/Losses | $-1023.98 (-1.33%) | $-0.72 (-1.10%) |
| Average True Range | (3.77%) | (1.66%) |