algo trading on FutuNiuNiu broker
Functions:
- Retrieves strategies' performances and positions
- Serve dashboard webpages
- Pause, Resume, Tune Algos
import FutuAlgo
if __name__ == '__main__':
app = FutuAlgo.WebApp()
app.run(port=8522, hook_ip='http://127.0.0.1:8000')
- Maintain Connection to Futu OpenD, broadcast data thorugh ZMQ
- Save data to MySQL db
- Data downloads, subscription changes
- Place, modify, cancel orders
- Install and run FutuOpenD: https://www.futunn.com/download/openAPI?lang=en-US
- Install and run MySQL database: https://www.mysql.com/downloads/
- Set environment variables:
- SANIC_HOST : host for sanic app (e.g. 0.0.0.0)
- SANIC_PORT: port for sanic app (e.g. 8000)
- FUTU_TRADE_PWD: trade unlock password for Futu
- FUTU_HOST: host for Futu OpenD
- FUTU_PORT: port for Futu OpenD
- ZMQ_PORT: port for ZMQ
- MYSQL_DB: name of the db
- MYSQL_HOST: host for MySQL
- MYSQL_USER: user for MySQL
- MYSQL_PWD: password for MySQLr
import FutuAlgo
INIT_DATATYPE = ['K_3M', 'K_5M', 'QUOTE']
INIT_TICKERS = ['HK.00700', 'HK_FUTURE.999010']
futu_hook = FutuAlgo.FutuHook()
futu_hook.subscribe(datatypes=INIT_DATATYPE, tickers=INIT_TICKERS)
futu_hook.run(fill_db=True)
Functions:
- Listen to FutuHook and receive price updates
- Trigger events on receiving data
- Retrieving strategy infos through Sanic(returns, positions, pending orders etc)
import FutuAlgo
class SMACrossover(FutuAlgo.CandlestickStrategy):
def __init__(self, short, long):
super().__init__(name='SMA Crossover ({}, {})'.format(short, long), bars_no=long + 1)
self.short = short
self.long = long
async def on_bar(self, datatype, ticker, df):
df['SMA_short'] = talib.SMA(df['close'], timeperiod=self.short)
df['SMA_long'] = talib.SMA(df['close'], timeperiod=self.long)
sma_short_last = df['SMA_short'].iloc[-2]
sma_short_cur = df['SMA_short'].iloc[-1]
sma_long_last = df['SMA_long'].iloc[-2]
sma_long_cur = df['SMA_long'].iloc[-1]
if (sma_short_last <= sma_long_last) and (sma_short_cur > sma_long_cur) and (self.get_qty(ticker) == 0):
self.buy_limit(ticker=ticker, quantity=self.cal_max_buy_qty(ticker),
price=self.get_price(ticker=ticker))
elif (sma_short_last >= sma_long_last) and (sma_short_cur < sma_long_cur) and (self.get_qty(ticker) > 0):
self.sell_limit(ticker=ticker, quantity=self.get_qty(ticker),
price=self.get_price(ticker=ticker))
async def on_order_update(self, order_id, df):
pass
async def on_orderbook(self, ticker, df):
pass
async def on_other_data(self, datatype, ticker, df):
pass
async def on_quote(self, ticker, df):
pass
async def on_tick(self, ticker, df):
pass
algo = SMACrossover(short=10, long=20)
algo.initialize(initial_capital=100000.0, margin=100000.0, mq_ip='tcp://127.0.0.1:8001',
hook_ip='http://127.0.0.1:8000',
hook_name='FUTU', trading_environment='SIMULATE',
trading_universe=['HK.00700', 'HK.01299'], datatypes=['K_3M'])
algo.run(5000)
import FutuAlgo
class SMACrossover(FutuAlgo.Backtest):
def __init__(self, short, long):
super().__init__(name='SMA Crossover ({}, {})'.format(short, long), bars_no=long+1)
self.short = short
self.long = long
async def on_bar(self, datatype, ticker, df):
df['SMA_short'] = talib.SMA(df['close'], timeperiod=self.short)
df['SMA_long'] = talib.SMA(df['close'], timeperiod=self.long)
sma_short_last = df['SMA_short'].iloc[-2]
sma_short_cur = df['SMA_short'].iloc[-1]
sma_long_last = df['SMA_long'].iloc[-2]
sma_long_cur = df['SMA_long'].iloc[-1]
if (sma_short_last <= sma_long_last) and (sma_short_cur > sma_long_cur) and (self.get_qty(ticker) == 0):
self.buy_limit(ticker=ticker, quantity=self.cal_max_buy_qty(ticker),
price=self.get_price(ticker=ticker))
elif (sma_short_last >= sma_long_last) and (sma_short_cur < sma_long_cur) and (self.get_qty(ticker) > 0):
self.sell_limit(ticker=ticker, quantity=self.get_qty(ticker),
price=self.get_price(ticker=ticker))
async def on_order_update(self, order_id, df):
pass
async def on_orderbook(self, ticker, df):
pass
async def on_other_data(self, datatype, ticker, df):
pass
async def on_quote(self, ticker, df):
pass
async def on_tick(self, ticker, df):
pass
if __name__ == '__main__':
algo = SMACrossover(short=16,long=32)
algo.initialize(initial_capital=200000.0, margin=200000.0, mq_ip='tcp://127.0.0.1:8001',
hook_ip='http://127.0.0.1:8000',
hook_name='FUTU', trading_environment='BACKTEST',
trading_universe=['HK.00700', 'HK.54544554','HK.00388'], datatypes=['K_DAY'], spread=0)
algo.backtest(start_date = '2020-04-01', end_date = '2020-05-01')
# Use tencent 0700 as benchmark. This will open a webbrowser showing the full report.
algo.report(benchmark='0700.HK')