Skip to content

Instantly share code, notes, and snippets.

@philomates
Created January 14, 2015 20:52
Show Gist options
  • Save philomates/2cf9ae2944d90e8049f7 to your computer and use it in GitHub Desktop.
Save philomates/2cf9ae2944d90e8049f7 to your computer and use it in GitHub Desktop.
Exploring some simple time-series questions
#!/bin/ipython3
"""
Exploring some simple time-series questions
Phillip Mates
Jan 14th, 2015
"""
import math
LOGGING = False
TESTING = True
INTERACTIVE_SHELL = False
# #############################################
# Some simple utils written ahead of time
# #############################################
def log(message):
""" simple logging.
Prints message if logging flag set
Args:
message: String
Returns:
Unit, with IO side-effects
"""
if LOGGING:
print(message)
def test(name, test_condition):
""" simple testing.
Runs test if testing flag is set.
Args:
name: String naming the test
test_condition: Boolean representing success of test
Returns:
Unit, with IO side-effects
"""
if TESTING:
if test_condition:
print("TEST PASSED:", name)
else:
print("TEST FAILED:", name)
# #############################################
# Data processing and Questions
# #############################################
def generate_data_point(t):
""" Generate a point in a particular time series.
The formula to generate the time series is
p(t) = 100 + sum[sin(t * c_i)] for c_i in
c = [46, 64, 98, 99, 101, 104, 106, 107, 109, 110, 111, 111, 111, 115, 115]
Args:
t: Integer representing time
Returns:
Float
"""
c = [46, 64, 98, 99, 101, 104, 106, 107, 109, 110, 111, 111, 111, 115, 115]
result = 100
for c_i in c:
result += math.sin(t * c_i)
return result
STOCK_TIME_SERIES = [generate_data_point(t) for t in range(260)]
def calculate_strategy_returns(stock_price_time_series):
""" Calculates returns of the following strategy applied to the input time series.
Hold the stock when it is within the open interval [98, 101] and
sell at the end of the time series if still holding.
Args:
stock_price_time_series: [List-of Float] representing stock price over time
Returns:
Float representing the amount gained by following the described strategy
"""
accumulated_returns = 0
# how many points in the times series have we looked at
points_processed = 0
# what was the price we last bought the stock out
last_bought_at = 0
# are we currently holding the stock?
holding = False
for price in stock_price_time_series:
points_processed += 1
if holding:
# we have the stock and it is the last point, then sell
if points_processed == len(stock_price_time_series):
accumulated_returns += price - last_bought_at
holding = False
log("S")
# continue holding stock
elif price >= 98 and price <= 101:
log("N")
# sell stock
else:
accumulated_returns += price - last_bought_at
holding = False
log("S")
else:
# buy stock
if price >= 98 and price <= 101:
log("B")
holding = True
last_bought_at = price
# else do nothing
else:
log("N")
return accumulated_returns
test("test strategy on series that breaks even",
calculate_strategy_returns([96, 97, 98, 102, 100, 100, 100, 96]) == 0)
# TODO: write more tests for calculate_strategy_returns
def strategy_to_percentage_return(stock_price_time_series):
""" Apply a strategy to stock price time series and calculate percentage returns at each step.
Args:
stock_price_time_series: [List-of Float] representing stock price over time
Returns:
[List-of Float] representing the percentage return at each point in time
"""
percentage_return_series = []
# how many points in the times series have we looked at
points_processed = 0
# what was the price we last bought the stock out
last_bought_at = 0
# are we currently holding the stock?
holding = False
for price in stock_price_time_series:
points_processed += 1
if holding:
# we have the stock and it is the last point, then sell
if points_processed == len(stock_price_time_series):
percentage_return_series.append((price - last_bought_at) / last_bought_at)
holding = False
log("S")
# continue holding stock
if price >= 98 and price <= 101:
percentage_return_series.append(0)
# sell stock
else:
percentage_return_series.append((price - last_bought_at) / last_bought_at)
holding = False
else:
# buy stock
if price >= 98 and price <= 101:
holding = True
last_bought_at = price
# XXX: Not sure if this is the correct percentage to append here
percentage_return_series.append(0)
# else do nothing
return percentage_return_series
# TODO: write tests for strategy_to_percentage_return
def total_cumulative_return(percentage_return_time_series):
""" Calculate the total cumulative return based on time series of individual return percentages.
Args:
percentage_return_time_series: [List-of Float] representing return percentage
Returns:
Float representing total return percentage
"""
# NOTE: Since I'm unfamiliar with cumulative percentage returns I'm
# following "Returns over multiple periods" formula from Wikipedia's "Rate
# of Return" page
cumulative_returns = 1
for rate in percentage_return_time_series:
cumulative_returns *= (1 + rate)
return cumulative_returns - 1
test("testing total return after two days of 10% gains",
total_cumulative_return([.1, .1]) >= .209 and
total_cumulative_return([.1, .1]) <= .211)
# What is the cumulative percentage return using this strategy:
# 1) simply on a percentage return basis
# e.g., day 1: 10%, day 2: 10%, total return would be 21% after two days.
print("Question 1: " + \
"based on applying the strategy over the stock price time series the " + \
"total cumulative return is",
total_cumulative_return(strategy_to_percentage_return(STOCK_TIME_SERIES)))
# 2) assuming $1000.00 of starting capital and only purchasing whole "shares"
# TODO
if __name__ == "__main__":
if INTERACTIVE_SHELL:
import code
code.interact(local=locals())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment