Tutorial: Smart Executor Strategy
We will create an trading application in this tutorial, which takes in simple commands from python API to adjust account risk. Use Python to generate signal and use Smart Executor to execute orders.
Steps to create an smart executor strategy
To create a flexible strategy, you will need do the following:
- Decide which exchange to trade.
- Add the symbols you plan to trade or listen for market data.
- Add price models.
- Add variables to generate signals.
- Add models.
- Add strategies.
- Create python script to generate signal and sending commands. see more details -> smart_executor reference
Configure
We use a json file to configure the trading applications. The file contains information about api keys, log path, and strategy components. Please update the API key information in the example configuration below:
{
"instance": {
"license_id":"apifiny001",
"license_key":"apifiny123456",
"log_path": "./logs/strategy_demo",
"name": "strategy_demo"
},
"ib_gateway": {
"ip": "127.0.0.1",
"port": 4002
},
"servers": {
"redis_server": "127.0.0.1"
},
"apikeys": {
"BINANCE": {
"key": "",
"secret": ""
},
"BINANCEUS": {
"key": "",
"secret": ""
},
"OKEX": {
"key": "",
"secret": "",
"pass": ""
}
},
"fees": {
"BINANCE": {
"make": 0.0,
"take": 0.00045
},
"BINANCEUS": {
"make": 0.0,
"take": 0.000462
},
"OKEX": {
"make": 0.0,
"take": 0.0002
}
},
"exchanges":
[
{"exchange":"BINANCEUS","trade_type":"Direct","market_data_type":"Direct"}
],
"risk_formulas": [
["Port_Risk", ["RiskFormula", {"components": [[["BTCUSDT", "BINANCEUS"], 1.0]]}]]
],
"accounts": [
[10001, ["Account", {"risk_formulas": ["Port_Risk"], "id": 10001}]]
],
"symbols": [
{"port": ["BTCUSDT", "BINANCEUS"], "cid": 10000}
],
"symbol_info": {
"BTCUSDT.BINANCEUS": {"ticksize": 0.01, "lotsize": 0.0001, "price_precision": 2.0, "min_order_size": 0.0001, "qty_precision": 6.0, "multiple": 1.0}
},
"players": [
["BTCUSDT.HUOBI_Player", ["CobJsonPlayer", {"port": ["BTCUSDT", "BINANCEUS"], "path": "/data/cc/prod/ccc_record_2"}]]
],
"samplers": [
["ts_basis", ["TimeSampler", {"halflife": 1, "msecs": 100}]]
],
"pricing_models": [
["BTCUSDT.HUOBI_midpx", ["MidPx", {"port": ["BTCUSDT", "BINANCEUS"]}]],
["BTCUSDT.HUOBI_Vwap", ["Vwap", {"port": ["BTCUSDT", "BINANCEUS"], "sampler": "ts_basis"}]]
],
"variables": [
["Zero", ["Const", {"value": 0.0}]]
],
"models": [
["Zero_m", ["LinearModel", {"variable": "Zero"}]]
],
"strategies": [
["BTCUSDT.BINANCEUS", ["CCEventMakerStrategy", {"symbol": "BTCUSDT", "trade_market": "BINANCEUS", "account": 10001, "dep_pm": "BTCUSDT.HUOBI_midpx", "model": "Zero_m", "VWap": "BTCUSDT.HUOBI_Vwap", "max_spread_bps": 5, "max_quote_frombbo_bps": 0.001, "update_quote_bps": 2, "quote_bps": 3, "allowed_bps": 5, "order_notional": 500, "max_notional": 2500, "max_risk": 2500, "cooloff": 100, "start_time": "00:30:00", "end_time": "23:59:59", "use_separate_logs": true, "close_mode": "none"}]]
]
}
Python Script
To create a functional python script, you will need following parts:
- Get data and process with your algorithim. We provide CCxtMarketData in the example as a simple way getting raw data.
- Use our ExecutorApi to send commands to our smart executor.
CCxtMarketData
Field | Description | Mandatory |
---|---|---|
exchange | The exchange you need data from. | Yes |
symbol_coin | The symbol coin you need data. | Yes |
symbol_basecoin | The basecoin of the symbol you need data. | Yes |
Function | Parameters | Mandatory |
---|---|---|
get_price | NA | Yes |
get_ema | sample time interval, halflife | Yes |
get_candle_data | sample time interval | Yes |
ExecutorApi
Field | Description | Mandatory |
---|---|---|
exchange | The exchange you need data from. | Yes |
symbol_coin | The symbol coin you need data. | Yes |
symbol_basecoin | The basecoin of the symbol you need data. | Yes |
Commands
Function | Description | Parameters |
---|---|---|
send_cmd_maker | Send position change you want, accumulate on smart executor side, and execute by making order. | instance name, trading direction, target position level |
send_cmd_taker | Send the position level you want, calculate order quantity on smart executor side, and execute by taking order. | instance name, target position level |
You only need to send position increase/decrease commands by send_cmd_maker, Smart Executor will automatically summarize all your command and execute;
Example
from apifiny.smart.ExecutorApi import ExecutorApi as ea
from apifiny.smart.examples.CcxtMarketData import CcxtMarketData as md
def strategy_live_demo(exchange, symbol_coin,symbol_basecoin,instance,targetLevel,interval,thresh,totalLevel):
commander = ea(exchange,symbol_coin,symbol_basecoin)
data= md(exchange, symbol_coin,symbol_basecoin)
count = 0
while True:
try:
data.get_price()
#test.get_candle_data("1m") #1m, 5m, 1h, 1d #By default you will have 500 metrics (if available)
data_long = data.get_ema("1m",5)
data_short = data.get_ema("1m",1)
ema_long = data_long['Close'][data_long['Close'].size-1]
ema_short = data_short['Close'][data_short['Close'].size-1]
except:
print("lost connection from ccxt")
time.sleep(interval)
continue
if ema_long < ema_short and totalLevel < 1:
if totalLevel < 0 and (abs(ema_long - ema_short)/data.mid) > thresh*0.0001:
print("thresh check: ",{(ema_long - ema_short)/data.mid}, " total level: ", totalLevel)
print("buy back: ema_long: ",{ema_long}, " ema_short: ", {ema_short}, "thresh", {thresh})
commander.send_cmd_maker(instance, "buy", targetLevel)
count += 1
totalLevel += targetLevel
elif totalLevel >= 0 and (abs(ema_long - ema_short)/data.mid) > thresh*(1+totalLevel/targetLevel)*0.0001:
print("thresh check: ",{(ema_long - ema_short)/data.mid}, " total level: ", totalLevel)
print("buy more: ema_long: ",{ema_long}, " ema_short: ", {ema_short}, "thresh", {thresh*(1+abs(totalLevel)/targetLevel)*0.0001})
commander.send_cmd_maker(instance, "buy", targetLevel)
count += 1
totalLevel += targetLevel
elif ema_long > ema_short and totalLevel > -1:
if totalLevel <= 0 and (abs(ema_long - ema_short)/data.mid) > thresh*(1+abs(totalLevel)/targetLevel)*0.0001:
print("thresh check: ",{(ema_long - ema_short)/data.mid}, " total level: ", totalLevel)
print("sell more: ema_long: ",{ema_long}, " ema_short: ", {ema_short}, "thresh", {thresh*(1+abs(totalLevel)/targetLevel)*0.0001})
commander.send_cmd_maker(instance, "sell", targetLevel)
count += 1
totalLevel -= targetLevel
elif totalLevel > 0 and (abs(ema_long - ema_short)/data.mid) > thresh*0.0001:
print("thresh check: ",{(ema_long - ema_short)/data.mid}, " total level: ", totalLevel)
print("sell back: ema_long: ",{ema_long}, " ema_short: ", {ema_short}, "thresh", {thresh})
commander.send_cmd_maker(instance, "sell", targetLevel)
count += 1
totalLevel -= targetLevel
time.sleep(interval)