Open untoreh opened 1 year ago
What are you suggesting by "embedding" Python strategies. Trality was great for writing Python strategies unfortunately they are closing https://www.trality.com/blog/trality-winding-down-product at end of month. Maybe you could find some ideas in the way Python strategies are written. See https://docs.trality.com/
Here is an example EMA CROSS AND RSI (Exponential moving average in combination with RSI.)
'''
In this bot an example of using the exponential moving average in combination with RSI is presented.
If you are new and trying to get started we recommend checking our https://app.trality.com/masterclass
For more information on each part of a trading bot, please visit our documentation pages: https://docs.trality.com
'''
'''
Initializing state object and setting number_offset_trades to 0 before the first bot execution.
'''
def initialize(state):
state.number_offset_trades = 0;
@schedule(interval="1h", symbol="BTCUSDT")
def handler(state, data):
'''
1) Compute indicators from data
'''
ema_long_ind = data.ema(40)
ema_short_ind = data.ema(20)
rsi_ind = data.rsi(14)
# on erroneous data return early (indicators are of NoneType)
if rsi_ind is None or ema_long_ind is None or ema_short_ind is None:
return
ema_long = ema_long_ind.last # Getting latest value for ema_long_ind from data object
ema_short = ema_short_ind.last
rsi = rsi_ind.last
current_price = data.close_last
'''
2) Fetch portfolio
> check liquidity (in quoted currency)
> resolve buy value
'''
portfolio = query_portfolio()
balance_quoted = portfolio.excess_liquidity_quoted
# we invest only 80% of available liquidity
buy_value = float(balance_quoted) * 0.80
'''
3) Fetch position for symbol
> has open position
> check exposure (in base currency)
'''
position = query_open_position_by_symbol(data.symbol,include_dust=False)
has_position = position is not None
'''
4) Resolve buy or sell signals
> create orders using the order api
> print position information
'''
if ema_short > ema_long and rsi < 30 and not has_position:
print("-------")
print("Buy Signal: creating market order for {}".format(data.symbol))
print("Buy value: ", buy_value, " at current market price: ", data.close_last)
order_market_value(symbol=data.symbol, value=buy_value) # creating market order
elif ema_short < ema_long and rsi > 70 and has_position:
print("-------")
logmsg = "Sell Signal: closing {} position with exposure {} at current market price {}"
print(logmsg.format(data.symbol,float(position.exposure),data.close_last))
close_position(data.symbol) # closing position
'''
5) Check strategy profitability
> print information profitability on every offsetting trade
'''
if state.number_offset_trades < portfolio.number_of_offsetting_trades:
pnl = query_portfolio_pnl()
print("-------")
print("Accumulated Pnl of Strategy: {}".format(pnl))
offset_trades = portfolio.number_of_offsetting_trades
number_winners = portfolio.number_of_winning_trades
print("Number of winning trades {}/{}.".format(number_winners,offset_trades))
print("Best trade Return : {:.2%}".format(portfolio.best_trade_return))
print("Worst trade Return : {:.2%}".format(portfolio.worst_trade_return))
print("Average Profit per Winning Trade : {:.2f}".format(portfolio.average_profit_per_winning_trade))
print("Average Loss per Losing Trade : {:.2f}".format(portfolio.average_loss_per_losing_trade))
# reset number offset trades
state.number_offset_trades = portfolio.number_of_offsetting_trades
In our case it is more about testing support for using python within a strategy (julia) module. It's not about offering a "simplified" interface for building strategies.
In the simplest case one can do
using Python
ping!(s, ts, args...) = pyimport(...)
There are untested scenarios (e.g. when backtesting or optimizing a strategy that call python code)
Although not really recommended, embedding python strategies is a very easy task.