-
Notifications
You must be signed in to change notification settings - Fork 3
/
buy_or_hold.py
135 lines (98 loc) · 3.68 KB
/
buy_or_hold.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import sys
from datetime import datetime
sys.path.append("../")
from stock_candle import StockCandle
# Experiment Parameters
nifty_olhc_filename = "../Data/Index/NIFTY 50_OLHC_DAILY_01011999_01012020.csv"
monthly_cash_increment = 1000
percentage_from_all_time_high = 10
"""
This method reads the NIFTY OLHC data from a csv file.
Please note that the data is originally sorted by date in descending order.
"""
def readNiftyCandles(reverse_candles=False):
file = open(nifty_olhc_filename, "r")
candles = []
# The first line in the csv is the header, so we need to skip that.
first_line_skipped = False
for line in file:
if not first_line_skipped:
first_line_skipped = True
continue
# The rows have data in the format Date, Open, High, Low, Close
row_splits = line.split(",")
date = datetime.strptime(row_splits[0], "%d %b %Y")
candle = StockCandle(
"NIFTY50",
date,
float(row_splits[1]),
float(row_splits[3]),
float(row_splits[2]),
float(row_splits[4]),
)
candles.append(candle)
if reverse_candles:
candles.reverse()
return candles
"""
This method populates all time high in candles.
NOTE: This method assumes that candles are sorted in chronological order, i.e. oldest candle comes first.
"""
def populateAllTimeHighs(candles):
all_time_high = 0
for candle in candles:
all_time_high = max(all_time_high, candle.close)
candle.all_time_high = all_time_high
return candles
candles = populateAllTimeHighs(readNiftyCandles(True))
def hasMonthChanged(previous_date, current_date):
if previous_date.month < current_date.month:
return True
if previous_date.year < current_date.year:
return True
return False
def runExperiment(candles, buyCandle):
# Setting up initialization parameters.
cash = 0
units_held = 0
previous_date = datetime.strptime("31 Dec 1998", "%d %b %Y")
current_value = 0
max_cash_held = 0
max_cash_held_buy_date = None
for candle in candles:
# Add to cash account on beginning of the month.
if hasMonthChanged(previous_date, candle.date):
cash += monthly_cash_increment
units_to_buy = buyCandle(candle, cash)
if units_to_buy > 0:
if cash > max_cash_held:
max_cash_held = cash
max_cash_held_buy_date = candle.date
units_held += units_to_buy
cash -= units_to_buy * candle.close
current_value = cash + units_held * candle.close
previous_date = candle.date
print("Cash to begin with: 0")
print("Monthly cash increment: 1000")
print("Final holding value: " + str(current_value))
print("Max cash held at one point: " + str(max_cash_held))
print("Max cash held buy date: " + max_cash_held_buy_date.__str__())
def buyCandleAsSoonAsYouHaveCash(candle, cash):
units_to_buy = round(cash / candle.close, 2)
# Taking care of rounding up errors
if units_to_buy * candle.close > cash:
units_to_buy -= 0.01
return units_to_buy
def buyOnFallFromAllTimeHigh(candle, cash):
fall_percentage = (
(candle.all_time_high - candle.close) / candle.all_time_high
) * 100
if fall_percentage < percentage_from_all_time_high:
return 0
return buyCandleAsSoonAsYouHaveCash(candle, cash)
print("Running strategy: BuyAsSoonAsYouHaveCash")
runExperiment(candles, buyCandleAsSoonAsYouHaveCash)
print("")
print("Running strategy: BuyOnFallFromAllTimeHigh")
print("Fall Percentage: " + str(percentage_from_all_time_high) + "%")
runExperiment(candles, buyOnFallFromAllTimeHigh)