-
Notifications
You must be signed in to change notification settings - Fork 0
/
forex.py
148 lines (114 loc) · 4.47 KB
/
forex.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
136
137
138
139
140
141
142
143
144
145
146
147
148
import csv
import collections
from settings import START_CAPITAL, SPREAD, LEVERAGE, NUMBER_TYPE
from datetime import datetime
VERSION_NUMBER = 1.2
print("API version {version}".format(version=VERSION_NUMBER))
DataRecord = collections.namedtuple('DataRecord', [
'timestamp', 'open', 'high', 'low', 'close', 'volume'])
def timecsv_to_datetime(timecsv):
year = int(timecsv[:4])
month = int(timecsv[4:6])
day = int(timecsv[6:8])
blank = timecsv[8]
hour = int(timecsv[9:11])
minute = int(timecsv[11:13])
seconds = int(timecsv[13:15])
return datetime(year, month, day, hour, minute, seconds)
class RawData(list):
def __init__(self, filename):
with open(filename, 'r') as csvfile:
spamreader = csv.reader(csvfile, delimiter=';', quotechar='|')
for row in list(spamreader):
row[0] = timecsv_to_datetime(row[0])
row[1:-1] = [NUMBER_TYPE(x) for x in row[1:-1]]
row[-1] = int(row[-1])
self.append(DataRecord(*row))
self.filename = filename
def __hash__(self):
return hash(self.filename)
class Simulation(object):
def __init__(self, raw_data, raw_history_data, spread=SPREAD,
start_capital=START_CAPITAL, leverage=LEVERAGE):
self.spread = NUMBER_TYPE(str(spread))
self._raw_data = raw_data
self._history_raw_data = raw_history_data
self.current_time = -1
self.capital = NUMBER_TYPE(start_capital)
self.currency = NUMBER_TYPE(0.0)
self.leverage = NUMBER_TYPE(leverage)
def __iter__(self):
return self
@property
def currency_value(self):
return self.currency * (self.price[0] if self.currency < 0
else self.price[1]) / self.leverage
@property
def all_value(self):
return self.capital + self.currency_value
def reset(self):
self.buy(-self.currency / self.leverage)
def buy(self, value):
if value >= 0:
self.currency += value * self.leverage
self.capital -= value * self.price[1]
else:
self.currency += value * self.leverage
self.capital -= value * self.price[0]
self.check_for_bankruptcy()
def sell(self, value):
return self.buy(-value)
def check_for_bankruptcy(self):
if self.all_value < 0:
raise ValueError("Bankrupt because of no money!")
if (self.all_value * self.leverage <
abs(self.currency / (self.price[0] if self.currency < 0
else self.price[1]))):
raise ValueError("Bankrupt because of leverage!")
def __next__(self):
return self.next()
def next(self):
self.check_for_bankruptcy()
self.current_time += 1
if self.current_time >= len(self._raw_data):
raise StopIteration()
result = self.price
return result
def history_price(self, index):
if index == 0:
return self.price
if index > 0:
raise ValueError("You cannot see the future.")
if self.current_time + index >= 0:
return (
self._raw_data[self.current_time + index].open,
self._raw_data[self.current_time + index].open + self.spread
)
else:
return (self._history_raw_data[self.current_time + index].open,
(self._history_raw_data[self.current_time + index].open +
self.spread))
@property
def timedelta(self):
try:
return (self._raw_data[self.current_time + 1].timestamp -
self._raw_data[self.current_time].timestamp
).total_seconds()
except IndexError:
return 1000000.0
@property
def price(self):
try:
return (self._raw_data[self.current_time].open,
self._raw_data[self.current_time].open + self.spread)
except IndexError:
return (self._raw_data[self.current_time - 1].close,
self._raw_data[self.current_time - 1].close + self.spread)
def simulate(raw_data, old_data, decisioner, executioner, **kwargs):
simulation = Simulation(raw_data, old_data, **kwargs)
for price in simulation:
decision = decisioner.decision(simulation)
executioner.execute(simulation, decision)
simulation.reset()
return simulation.all_value
# this is the end of library things