Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def record_data(context, data, data_manager=None):
price = data.current(context.asset, "price")
cash = context.portfolio.cash
data_payload = {}
if data_manager is not None:
data_payload = data_manager.record_data(context, data)
# Save values for later inspection
record(price=price, cash=cash, **data_payload)
# Get price, open, high, low, close
prices = data.history(
context.asset,
bar_count=context.BARS,
fields=["price", "open", "high", "low", "close"],
frequency="1d",
)
# Save the prices and analysis to send to analyze
context.prices = prices
context.price = data.current(context.asset, "price")
if price < 0.75 * peak:
context.IS_MARKET_BEAR = True
elif price > 1.2 * bottom:
context.IS_MARKET_BEAR = False
if context.IS_MARKET_BEAR:
order_target_percent(context.asset, 0.3)
else:
order_target_percent(context.asset, 0.75)
Portfolio_cumulative_return = (
context.portfolio.portfolio_value / context.portfolio.starting_cash - 1
) * 100
# Save values for later inspection
record(
price=price,
peak=peak,
bottom=bottom,
cash=context.portfolio.cash,
leverage=context.account.leverage,
Portfolio_cumulative_return=Portfolio_cumulative_return,
)
def record_data(self, context, data, datasets):
date = context.blotter.current_dt.date()
record_payload = {}
if date not in self.df.index:
return record_payload
for col in datasets:
current_val = self.column_by_date(col, date)
record_payload[col] = current_val
log.info('{}: {}'.format(col, current_val))
record(**record_payload)
current = data.current(context.market, fields=["close", "volume"])
price = current["close"]
# If base_price is not set, we use the current value. This is the
# price at the first bar which we reference to calculate price_change.
if context.base_price is None:
context.base_price = price
price_change = (price - context.base_price) / context.base_price
cash = context.portfolio.cash
# Now that we've collected all current data for this frame, we use
# the record() method to save it. This data will be available as
# a parameter of the analyze() function for further analysis.
record(volume=current["volume"], price=price, price_change=price_change, rsi=rsi[-1], cash=cash)
# We are trying to avoid over-trading by limiting our trades to
# one per day.
if context.traded_today:
return
# TODO: retest with open orders
# Since we are using limit orders, some orders may not execute immediately
# we wait until all orders are executed before considering more trades.
orders = get_open_orders(context.market)
if len(orders) > 0:
log.info("exiting because orders are open: {}".format(orders))
return
# Exit if we cannot trade
if not data.can_trade(context.asset):
return
) * 100
# Trading logic: rebalance to a 0.5 investment ratio every time the price
# of the asset doubles or decreases to half the initial price
if price > context.base_price * 1.1:
order_target_percent(context.asset, 0.5)
context.base_price = data.current(context.asset, "price")
elif price < context.base_price / 1.1:
order_target_percent(context.asset, 0.5)
context.base_price = data.current(context.asset, "price")
price = data.current(context.asset, "price")
# Save values for later inspection
record(
price=price,
base_price=context.base_price,
cash=context.portfolio.cash,
leverage=context.account.leverage,
Portfolio_cumulative_return=Portfolio_cumulative_return,
Asset_cumulative_return=Asset_cumulative_return,
)
log.info('got rsi: {}'.format(rsi))
# Buying more when RSI is low, this should lower our cost basis
if rsi <= 30:
buy_increment = 1
elif rsi <= 40:
buy_increment = 0.5
elif rsi <= 70:
buy_increment = 0.2
else:
buy_increment = 0.1
cash = context.portfolio.cash
log.info('base currency available: {cash}'.format(cash=cash))
record(
price=price,
rsi=rsi,
)
orders = context.blotter.open_orders
if orders:
log.info('skipping bar until all open orders execute')
return
is_buy = False
cost_basis = None
if context.asset in context.portfolio.positions:
position = context.portfolio.positions[context.asset]
cost_basis = position.cost_basis
log.info(
# If for example,
# selling price = 50
# buying price = 25
# expected gap = 1
# If follows that,
# selling price - buying price / buying price
# 50 - 25 / 25 = 1
gap = (selling_price - buying_price) / buying_price
log.info(
'the price gap: {gap} ({gap_percent}%)'.format(
gap=gap,
gap_percent=gap * 100
)
)
record(buying_price=buying_price, selling_price=selling_price, gap=gap)
# Waiting for orders to close before initiating new ones
for exchange in context.trading_pairs:
asset = context.trading_pairs[exchange]
if asset in context.blotter.open_orders:
log.info(
'found {order_count} open orders on {exchange_name} '
'skipping bar until all open orders execute'.format(
order_count=len(context.blotter.open_orders(asset)),
exchange_name=exchange.name
)
)
return
# Consider the least ambitious entry point first
# Compute averages
# history() has to be called with the same params
# from above and returns a pandas dataframe.
short_mavg = data.history(context.sym, 'price', 100, '1d').mean()
long_mavg = data.history(context.sym, 'price', 300, '1d').mean()
# Trading logic
if short_mavg > long_mavg:
# order_target orders as many shares as needed to
# achieve the desired number of shares.
order_target(context.sym, 100)
elif short_mavg < long_mavg:
order_target(context.sym, 0)
# Save values for later inspection
record(AAPL=data.current(context.sym, "price"),
short_mavg=short_mavg,
long_mavg=long_mavg)
def handle_data(context, data):
price = data.current(context.asset, 'price')
record(btc=price)
# Only ordering if it does not have any position to avoid trying some
# tiny orders with the leftover btc
pos_amount = context.portfolio.positions[context.asset].amount
if pos_amount > 0:
return
# Adding a limit price to workaround an issue with performance
# calculations of market orders
order_target_percent(
context.asset, 1, limit_price=price * 1.01
)
rsi = talib.RSI(prices.values, timeperiod=16)[-1]
log.info("got rsi {}".format(rsi))
signal = None
if rsi < context.RSI_OVERSOLD:
signal = "long"
# Making sure that the price is still current
price = data.current(context.asset, "close")
cash = context.portfolio.cash
log.info(
"base currency available: {cash}, cap: {cap}".format(cash=cash, cap=context.MAX_HOLDINGS)
)
volume = data.current(context.asset, "volume")
price_change = (price - context.base_price) / context.base_price
record(
price=price,
price_change=price_change,
rsi=rsi,
volume=volume,
cash=cash,
starting_cash=context.portfolio.starting_cash,
leverage=context.account.leverage,
)
_handle_buy_sell_decision(context, data, signal, price)