Skip to content
This repository was archived by the owner on Mar 12, 2023. It is now read-only.

Commit aaa8bb9

Browse files
Merge pull request #4 from HarryLudemann/start-script
Adding async to run method
2 parents b5760a1 + 7797059 commit aaa8bb9

3 files changed

Lines changed: 66 additions & 65 deletions

File tree

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
with codecs.open(os.path.join(here, "README.md"), encoding="utf-8") as fh:
88
long_description = "\n" + fh.read()
99

10-
VERSION = '0.0.2'
10+
VERSION = '0.0.3'
1111
DESCRIPTION = 'Run/Backtest/Create Easy Python Trading Algorithms'
1212
LONG_DESCRIPTION = 'A package that allows easy to write, run and backtest algorithms for stocks, forex and crypto from pre-written data sources eg. alpha vantage, yfinance'
1313

trader/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
from trader import data
2-
from trader.start import backtest, standard_backtest, run, StockAlgorithm, ForexAlgorithm
2+
from trader.start import backtest, run, StockAlgorithm, ForexAlgorithm

trader/start.py

Lines changed: 64 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,10 @@ def set_from_currency(self, to_currency):
7979

8080

8181

82-
backtest_algorithms = [] # list of algorithms to backtest for async
8382
async def async_backtest(algorithm):
8483
"""" Async method to backtest given algorithm object, gets data and passes each row to on_data method - dont call"""
8584
if algorithm.Active == False: return
85+
print(f'Getting {algorithm.Name} data, from {algorithm.Data_Source}')
8686
if hasattr(algorithm, 'Symbol'): # if algorithm is stock algo
8787
df = await getattr(data, f'get_{algorithm.Data_Source}_stock')(algorithm)
8888

@@ -97,7 +97,7 @@ async def async_backtest(algorithm):
9797
for i in range(len(df)):
9898
algorithm.on_data(df.iloc[i])
9999
print(f'Finished: {algorithm.Name}: {start_date} to, {end_date} interval: {algorithm.Interval} Data-Source: {algorithm.Data_Source}')
100-
return algorithm.stats()
100+
algorithm.stats()
101101

102102

103103
async def create_backtest_tasks():
@@ -106,87 +106,88 @@ async def create_backtest_tasks():
106106
tasks = [asyncio.ensure_future(async_backtest(algo)) for algo in backtest_algorithms]
107107
# wait for all tasks to complete
108108
await asyncio.wait(tasks)
109-
return tasks
110109

111110

112111
def backtest(algorithms):
113112
""" Backtest method passed list of algorithms, calls on data for methods"""
114-
for algorithm in algorithms:
115-
backtest_algorithms.append(algorithm)
113+
global backtest_algorithms
114+
backtest_algorithms = algorithms
116115
try:
116+
loop = asyncio.new_event_loop()
117+
asyncio.set_event_loop(loop)
117118
loop = asyncio.get_event_loop()
118119
#loop.set_debug(1)
119-
tasks = loop.run_until_complete(create_backtest_tasks())
120-
for algo in tasks:
121-
print(algo.result())
120+
loop.run_until_complete(create_backtest_tasks())
122121
except Exception as e:
123122
print(e)
124123
finally:
125124
loop.close()
126125

127126

128-
def standard_backtest(algorithm):
129-
""" standard Method to backtest given algorithm object, gets data and passes each row to on_data method """
130-
if algorithm.Active == False: return
131-
if hasattr(algorithm, 'Symbol'): # if algorithm is stock algo
132-
df = getattr(data, f'get_standard_{algorithm.Data_Source}_stock')(algorithm)
133-
134-
elif hasattr(algorithm, 'From_Currency'): # if algorithm is forex method
135-
df = getattr(data, f'get_standard_{algorithm.Data_Source}_forex')(algorithm)
136-
137-
start_date = df.index[0] # start date of data
138-
end_date = df.index[-1] # end date of data
139-
140-
print(f'Back Testing: {algorithm.Name}: {start_date} to, {end_date} interval: {algorithm.Interval} Data-Source: {algorithm.Data_Source}')
141-
142-
# need alternative, somewhat slow
143-
for i in range(len(df)):
144-
algorithm.on_data(df.iloc[i])
145-
146-
print(f'Finished: {algorithm.Name}: {start_date} to, {end_date} interval: {algorithm.Interval} Data-Source: {algorithm.Data_Source}')
147127

128+
async def async_run(algorithm):
129+
""" runs given algorithm object if interval time has passed - dont call (used for run method)"""
130+
# get algorithms interval in minutes
131+
if algorithm.Interval[-1] == 'm':
132+
if algorithm.Interval[0] == '1' and algorithm.Interval[1] == '5': # 15 minute interval
133+
algo_interval_minutes = 15
134+
elif algorithm.Interval[0] == '1': # 1 minute interval
135+
algo_interval_minutes = 1
136+
elif algorithm.Interval[0] == '5': # 5 minute interval
137+
algo_interval_minutes = 5
138+
elif algorithm.Interval[0] == '3': # 30 minute interval
139+
algo_interval_minutes = 30
140+
elif algorithm.Interval[0] == '6': # 60 minute interval
141+
algo_interval_minutes = 60
142+
elif algorithm.Interval[-1] == 'd': # 1 day interval
143+
algo_interval_minutes = 1440
144+
elif algorithm.Interval[-1] == 'w': # 1 week interval
145+
algo_interval_minutes = 10080
146+
elif algorithm.Interval[-1] == 'm': # 1 month interval
147+
algo_interval_minutes = 43200
148+
elif algorithm.Interval[-1] == 'y': # 1 year interval
149+
algo_interval_minutes = 525600
150+
151+
# if time to run algorithm
152+
if minutes_ran % algo_interval_minutes == 0:
153+
# get appropriate data
154+
if hasattr(algorithm, 'Symbol'): # if algorithm is stock algo
155+
df = await getattr(data, f'get_{algorithm.Data_Source}_stock')(algorithm)
156+
157+
elif hasattr(algorithm, 'From_Currency'): # if algorithm is forex method
158+
df = await getattr(data, f'get_{algorithm.Data_Source}_forex')(algorithm)
159+
160+
algorithm.on_data(df.iloc[-1]) # call on data with last row in df
161+
algorithm.stats()
162+
await asyncio.sleep(0)
163+
164+
165+
async def create_run_tasks():
166+
""" Create of async_run method for all run algorithms"""
167+
tasks = [asyncio.ensure_future(async_run(algo)) for algo in run_algorithms]
168+
# wait for all tasks to complete
169+
await asyncio.wait(tasks)
148170

149171

150172
def run(Algorithms):
151173
""" Pass list of objects runs objects, returns nothing"""
152174
# currently not setup to be updatable while running
153-
start_time = time.time()
154-
Algorithms = [x for x in Algorithms if x.Active]
155-
minutes_ran = 0
175+
start_time = time.time() # for scheduling getting rest of of minute
176+
global run_algorithms
177+
run_algorithms = [x for x in Algorithms if x.Active]
178+
global minutes_ran
179+
minutes_ran = 0
156180
while True:
157-
for algorithm in Algorithms:
158-
# get algorithms interval in minutes
159-
if algorithm.Interval[-1] == 'm':
160-
if algorithm.Interval[0] == '1' and algorithm.Interval[1] == '5': # 15 minute interval
161-
algo_interval_minutes = 15
162-
elif algorithm.Interval[0] == '1': # 1 minute interval
163-
algo_interval_minutes = 1
164-
elif algorithm.Interval[0] == '5': # 5 minute interval
165-
algo_interval_minutes = 5
166-
elif algorithm.Interval[0] == '3': # 30 minute interval
167-
algo_interval_minutes = 30
168-
elif algorithm.Interval[0] == '6': # 60 minute interval
169-
algo_interval_minutes = 60
170-
elif algorithm.Interval[-1] == 'd': # 1 day interval
171-
algo_interval_minutes = 1440
172-
elif algorithm.Interval[-1] == 'w': # 1 week interval
173-
algo_interval_minutes = 10080
174-
elif algorithm.Interval[-1] == 'm': # 1 month interval
175-
algo_interval_minutes = 43200
176-
elif algorithm.Interval[-1] == 'y': # 1 year interval
177-
algo_interval_minutes = 525600
178-
179-
# if time to run algorithm
180-
if minutes_ran % algo_interval_minutes == 0:
181-
# get appropriate data
182-
if hasattr(algorithm, 'Symbol'): # if algorithm is stock algo
183-
df = getattr(data, f'get_{algorithm.Data_Source}_stock')(algorithm)
184-
185-
elif hasattr(algorithm, 'From_Currency'): # if algorithm is forex method
186-
df = getattr(data, f'get_{algorithm.Data_Source}_forex')(algorithm)
187-
188-
algorithm.on_data(df.iloc[-1]) # call on data with last row in df
189-
181+
try:
182+
loop = asyncio.new_event_loop()
183+
asyncio.set_event_loop(loop)
184+
loop = asyncio.get_event_loop()
185+
#loop.set_debug(1)
186+
loop.run_until_complete(create_run_tasks())
187+
except Exception as e:
188+
print(e)
189+
finally:
190+
loop.close()
190191

191192
# wait for remainder of minute
192193
time.sleep(60.0 - ((time.time() - start_time) % 60.0))

0 commit comments

Comments
 (0)