Skip to content
This repository was archived by the owner on May 8, 2021. It is now read-only.

Commit c6de034

Browse files
commit
1 parent 15c303a commit c6de034

File tree

6 files changed

+186
-10
lines changed

6 files changed

+186
-10
lines changed

back.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
from libkloudtrader.algorithm import *
2+
import libkloudtrader.analysis as analysis
3+
import pandas as pd
4+
import numpy as np
5+
6+
7+
8+
def ba(backtest,data):
9+
10+
data['high']=data.close.shift(1).rolling(window=5).max()
11+
data['low']=data.close.shift(1).rolling(window=5).min()
12+
data['avg']=analysis.ma(data.close,5)
13+
buy=(data.close>data.high)
14+
sell=(data.close<data.avg)
15+
#short=(data.close<data.low)
16+
#cover=(data.close>data.avg)
17+
if buy.tail(1).bool():
18+
backtest.buy(5)
19+
elif sell.tail(1).bool():
20+
backtest.sell(5)
21+
else:
22+
print('No trade')
23+
24+
#rets=analysis.daily_returns(data.close)
25+
#data['volatility']=analysis.moving_volatility(rets,1)
26+
#data['slip']=data.high-data.close
27+
28+
29+
30+
31+
32+
run_backtest(ba,['AAPL'],data="US_STOCKS_daily",start_date='2018-01-01',end_date='2019-01-01')

sma_live.py renamed to backtest.md

File renamed without changes.

libkloudtrader/algorithm.py

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from typing import Any, List
22
import random
33
import time
4+
import datetime
45
import numpy as np
56
import pandas as pd
67
import libkloudtrader.stocks as stocks
@@ -10,15 +11,18 @@
1011
from libkloudtrader.logs import start_logger
1112
import libkloudtrader.backtest as bt
1213
import libkloudtrader.crypto as crypto
13-
import asyncio
14+
import libkloudtrader.analysis as analysis
15+
16+
17+
1418
#pd.set_option('display.max_columns', None) # or 1000
1519
#pd.set_option('display.max_rows', None) # or 1000
1620
#pd.set_option('display.max_colwidth', -1) # or 199
1721

1822
logger = start_logger(__name__, ignore_module='libkloudtrader.analysis')
1923

2024

21-
def backtest(strategy: str,
25+
def run_backtest(strategy: str,
2226
symbol_bucket: List[str],
2327
data: str,
2428
start_date: Any,
@@ -27,23 +31,42 @@ def backtest(strategy: str,
2731
preferred_benchmark: str = 'SPY',
2832
data_interval: str = '1d',
2933
initial_capital: float = 100000,
30-
commission: float = 0):
34+
commission: float = 0,
35+
slippage=True):
3136
"""Backtester function"""
3237
try:
3338
logger.info(
3439
'Starting Backtest for {} from {} to {} with initial capital = {}'.
3540
format(strategy.__name__, start_date, end_date, initial_capital))
3641
data_to_backtest_on = Data_Types[data].value
42+
for symbol in symbol_bucket:
43+
data_batch = data_to_backtest_on(symbol,
44+
start_date,
45+
end_date
46+
)
47+
batch = processing.Buffer(len(data_batch), dtype=object)
48+
backtest=bt.Backtest(capital=100000,commission=1,enable_slippage=True)
49+
for index, bar in data_batch.iterrows():
50+
batch.append(bar)
51+
backtest.update_bar(index,bar)
52+
data_batch = pd.DataFrame(batch)
53+
54+
locals()['strategy'](backtest,data_batch)
55+
print(backtest.get_trade_log)
56+
57+
'''
3758
for symbol in symbol_bucket:
3859
data_batch = data_to_backtest_on(symbol,
3960
start_date,
4061
end_date,
4162
interval=data_interval)
4263
for symbol in symbol_bucket:
64+
65+
4366
a = bt.Backtest(locals()['strategy'](data_batch),
4467
preferred_price_point)
4568
print(a.preferred_price_point)
46-
'''
69+
4770
signals=locals()['strategy'](data_batch)
4871
df=pd.DataFrame()
4972
df['buy']=signals['buy']
@@ -62,7 +85,7 @@ def backtest(strategy: str,
6285
#df['positions in '+symbol]=100*df['positions']
6386
#print(bt.trades)
6487

65-
logger.info("Received Signals from {}".format(strategy.__name__))
88+
logger.info("Received Signals from {}".format(strategy.__name__))
6689

6790
except (KeyboardInterrupt, SystemExit):
6891
print('\n')
@@ -80,29 +103,33 @@ def backtest(strategy: str,
80103
#print(locals()[a](symbol, start_date, end_date))
81104

82105

83-
def live_trade(strategy: str,
106+
def run_live(strategy: str,
84107
symbol_bucket: list,
85108
data_feed_type: str,
86-
exempted_states: list = ['close'],
109+
exempted_states: list = [''],
110+
exempted_days:list=[''],
111+
exempted_dates:list=[''],
87112
batch_size: int = 1000,
88-
data_feed_delay: float = 0.0,
113+
data_feed_delay: float = 1.0,
89114
fake_feed: bool = False):
90115
try:
91116
logger.info("{} is now entering the live markets. 📈\n".format(
92117
strategy.__name__))
118+
[x.lower() for x in exempted_states]
119+
[x.lower() for x in exempted_days]
93120
if isinstance(symbol_bucket, list):
94121
symbol_bucket = np.array(symbol_bucket)
95122
elif type(symbol_bucket) not in (numpy.ndarray, list):
96123
raise TypeError('Symbol bucket must be a list or numpy array')
97124
if data_feed_type not in ('CRYPTO_live_feed', 'US_STOCKS_live_feed',
98125
'CRYPTO_live_feed_level2'):
99126
raise InvalidDataFeedType(
100-
'This Data Feed is not available for live trading. Please use libkloudtrader.algorithm.backtest() for backtesting or using hisotrical data.'
127+
'This Data Feed is not available for live trading.'
101128
)
102129
if data_feed_type in ("CRYPTO_live_feed", 'CRYPTO_live_feed_level2'):
103130
data_feed_delay = crypto.exchange_attribute('rateLimit')
104131
data_feed = Data_Types[data_feed_type].value
105-
while stocks.intraday_status()['state'] not in exempted_states:
132+
while stocks.intraday_status()['state'] not in exempted_states: #and datetime.datetime.now().strftime("%A").lower() not in exempted_days:
106133
batch = processing.Buffer(batch_size, dtype=object)
107134
while len(batch) < batch_size:
108135
for symbol in symbol_bucket:

libkloudtrader/backtest.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
'''
12
import pandas as pd
23
from libkloudtrader.exceptions import InvalidPricePoint
34
@@ -31,3 +32,91 @@ def data(self):
3132
@property
3233
def preferred_price_point(self):
3334
return self.default_price
35+
'''
36+
import numpy as np
37+
import pandas as pd
38+
39+
class Backtest():
40+
def __init__(self,capital:float,commission:float,enable_slippage:bool):
41+
"""Init backtest"""
42+
self.capital=capital
43+
self.bar=0
44+
self.position=0
45+
self.commission=commission
46+
self.enable_slippage=enable_slippage
47+
self.slippage=0
48+
self.trades_log=pd.DataFrame(columns=['datetime','trade type','price','fill price','order cost'])
49+
50+
51+
def buy(self,quantity):
52+
'''emulates a buy order'''
53+
self.capital-=self.order_cost
54+
self.update_positions(quantity)
55+
self.update_trade_logs(datetime=self.bar.datetime,trade_type='Buy',price=self.bar.close,fill_price=self.fill_price,order_cost=self.order_cost)
56+
print('Bought {} of stocks @ {} but price is {}'.format(quantity,self.order_cost,self.bar.close))
57+
58+
59+
def sell(self,quantity):
60+
'''emulates a sell order'''
61+
if self.position!=0:
62+
self.capital+=self.order_cost
63+
self.update_positions(-1*quantity)
64+
self.update_trade_logs(datetime=self.bar.datetime,trade_type='Sell',price=self.bar.close,fill_price=self.fill_price,order_cost=-1*self.order_cost)
65+
print('Sold {} of stocks @ {} but price is {}'.format(quantity,self.order_cost,self.bar.close))
66+
else:
67+
print('No position to close')
68+
69+
def update_trade_logs(self,datetime,trade_type,price,fill_price,order_cost):
70+
df=pd.DataFrame([{'datetime':datetime,'trade type':trade_type,'price':price,'fill price':fill_price,'order cost':order_cost}])
71+
self.trades_log=self.trades_log.append(df)
72+
73+
74+
@property
75+
def get_trade_log(self):
76+
self.trades_log.set_index('datetime',inplace=True)
77+
return self.trades_log
78+
79+
def update_bar(self,index,bar):
80+
self.bar=bar
81+
self.bar.datetime=index
82+
83+
def update_positions(self,quantity):
84+
self.position+=quantity
85+
86+
@property
87+
def calculate_commission(self):
88+
commiss=(self.commission/100)*self.bar.close
89+
return commiss
90+
91+
@property
92+
def calculate_slippage(self):
93+
'''how is slippage calculated?'''
94+
'''slippage should not be more than 2% in most of the trades. so we generate a random percentage b/w 0-2.use that number as %age'''
95+
if self.enable_slippage:
96+
slippage_percent= np.random.uniform(low=0, high=0.02)
97+
slippage=slippage_percent*self.bar.close
98+
return slippage
99+
return 0.0
100+
101+
@property
102+
def fill_price(self):
103+
return self.bar.close+self.calculate_slippage
104+
105+
106+
@property
107+
def order_cost(self):
108+
return self.fill_price+self.calculate_commission
109+
110+
111+
@property
112+
def getcapital(self):
113+
return self.capital
114+
115+
@property
116+
def getbar(self):
117+
return self.bar
118+
119+
@property
120+
def getposition(self):
121+
return self.position
122+

libkloudtrader/crypto.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -776,6 +776,7 @@ def incoming_tick_data_handler(symbol: str,
776776
fake_feed: bool = False):
777777
latest_orderbook_entry = order_book(symbol, number_of_data_points=1)
778778
latest_trades = trades(symbol, number_of_data_points=1)
779+
latest_price=latest_price_info(symbol)
779780
latest_orderbook_entry_dict = {}
780781
latest_orderbook_entry_dict['symbol'] = symbol
781782
latest_orderbook_entry_dict['ask'] = latest_orderbook_entry['asks'][0][
@@ -792,6 +793,10 @@ def incoming_tick_data_handler(symbol: str,
792793
latest_orderbook_entry_dict['price'] = latest_trades[0]['price']
793794
latest_orderbook_entry_dict['tradesize'] = latest_trades[0]['amount']
794795
latest_orderbook_entry_dict['tradedate'] = latest_trades[0]['datetime']
796+
latest_orderbook_entry_dict['open']=latest_price['open']
797+
latest_orderbook_entry_dict['high']=latest_price['high']
798+
latest_orderbook_entry_dict['low']=latest_price['low']
799+
latest_orderbook_entry_dict['close']=latest_price['close']
795800
return latest_orderbook_entry_dict
796801

797802

live.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from libkloudtrader.algorithm import *
2+
import pandas as pd
3+
import libkloudtrader.analysis as analysis
4+
5+
def crypto_turtle(data):
6+
data['high']=data.price.shift(1).rolling(window=5).max()
7+
data['low']=data.price.shift(1).rolling(window=5).min()
8+
data['avg']=analysis.ma(data.price,5)
9+
buy=data.price>data.high
10+
sell=data.price<data.avg
11+
short=data.price<data.low
12+
cover=data.price>data.avg
13+
if buy.tail(1).bool():
14+
logger.info('Buy signal')
15+
if sell.tail(1).bool():
16+
logger.info('Sell signal')
17+
if short.tail(1).bool():
18+
logger.info('Short signal')
19+
if cover.tail(1).bool():
20+
logger.info('Cover signal')
21+
22+
23+
live_trade(crypto_turtle,symbol_bucket=['BTC/USD'],data_feed_type="CRYPTO_live_feed")

0 commit comments

Comments
 (0)