def _algo(self): pf.TradeLog.cash = self.capital pf.TradeLog.margin = pf.Margin.CASH for i, row in enumerate(self.ts.itertuples()): date = row.Index.to_pydatetime() high = row.high low = row.low close = row.close end_flag = pf.is_last_row(self.ts, i) # buy if self.tlog.shares == 0: self.tlog.buy(date, close) print("{0} BUY {1} {2} @ {3:.2f}".format( date, self.tlog.shares, self.symbol, close)) # sell elif end_flag: shares = self.tlog.sell(date, close) print("{0} SELL {1} {2} @ {3:.2f}".format( date, -shares, self.symbol, close)) # record daily balance self.dbal.append(date, high, low, close)
def _algo(self): """ Algo: 1. The SPY closes above its upper band, buy 2. If the SPY closes below its lower band, sell your long position. """ pf.TradeLog.cash = self.capital for i, row in enumerate(self.ts.itertuples()): date = row.Index.to_pydatetime() high = row.high low = row.low close = row.close end_flag = pf.is_last_row(self.ts, i) shares = 0 # buy if self.tlog.shares == 0: if row.regime > 0: shares = self.tlog.buy(date, close) # sell else: if row.regime < 0 or end_flag: shares = self.tlog.sell(date, close) if shares > 0: pf.DBG("{0} BUY {1} {2} @ {3:.2f}".format( date, shares, self.symbol, close)) elif shares < 0: pf.DBG("{0} SELL {1} {2} @ {3:.2f}".format( date, -shares, self.symbol, close)) # record daily balance self.dbal.append(date, high, low, close)
def _algo(self): """ Algo: 1. S&P 500 index closes above its 200 day moving average 2. The stock closes above its upper band, buy 3. S&P 500 index closes below its 200 day moving average 4. The stock closes below its lower band, sell your long position. """ pf.TradeLog.cash = self.capital pf.TradeLog.seq_num = 0 for i, row in enumerate(self.ts.itertuples()): date = row.Index.to_pydatetime() high = row.high low = row.low close = row.close end_flag = pf.is_last_row(self.ts, i) upper_band = row.sma + row.sma * self.percent_band lower_band = row.sma - row.sma * self.percent_band shares = 0 # Sell Logic # First we check if an existing position in symbol should be sold # - sell if (use_regime_filter and regime < 0) # - sell if price closes below lower_band # - sell if end of data if self.tlog.shares > 0: if ((self.regime_filter and row.regime < 0) or close < lower_band or end_flag): # enter sell in trade log shares = self.tlog.sell(date, close) # Buy Logic # First we check to see if there is an existing position, if so do nothing # - Buy if (regime > 0 or not use_regime_filter) # and price closes above upper_band # and (use_regime_filter and regime > 0) else: if ((row.regime > 0 or not self.regime_filter) and close > upper_band): # enter buy in trade log shares = self.tlog.buy(date, close) if shares > 0: pf.DBG("{0} BUY {1} {2} @ {3:.2f}".format( date, shares, self.symbol, close)) elif shares < 0: pf.DBG("{0} SELL {1} {2} @ {3:.2f}".format( date, -shares, self.symbol, close)) # record daily balance self.dbal.append(date, high, low, close)
def _algo(self): """ Algo: 1. The SPY is above its 200-day moving average 2. The SPY closes at a X-day low, buy some shares. If it falls further, buy some more, etc... 3. If the SPY closes at a X-day high, sell your entire long position. """ pf.TradeLog.cash = self.capital for i, row in enumerate(self.ts.itertuples()): date = row.Index.to_pydatetime() high = row.high low = row.low close = row.close end_flag = pf.is_last_row(self.ts, i) shares = 0 # Sell Logic # First we check if an existing position in symbol should be sold # - sell if price close sets a new period_high # - sell if end of data if (self.tlog.num_open_trades() > 0 and (close == row.period_high or end_flag)): # enter sell in trade log shares = self.tlog.sell(date, close) # Buy Logic # First we check to see if we have exceeded max_positions, if so do nothing # - Buy if regime > 0 # and price close sets a new period_low elif (self.tlog.num_open_trades() < self.max_positions and row.regime > 0 and close == row.period_low): # calc number of shares buying_power = self.tlog.calc_buying_power(price=close) cash = buying_power / (self.max_positions - self.tlog.num_open_trades()) shares = self.tlog.calc_shares(price=close, cash=cash) # enter buy in trade log self.tlog.buy(date, close, shares) if shares > 0: pf.DBG("{0} BUY {1} {2} @ {3:.2f}".format( date, shares, self.symbol, close)) elif shares < 0: pf.DBG("{0} SELL {1} {2} @ {3:.2f}".format( date, -shares, self.symbol, close)) else: pass # HOLD # record daily balance self.dbal.append(date, high, low, close)
def _algo(self): """ Algo: 1. The SPY is above its 200-day moving average 2. The SPY closes at a X-day low, buy some shares. If it falls further, buy some more, etc... 3. If the SPY closes at a X-day high, sell your entire long position. """ pf.TradeLog.cash = self.capital pf.TradeLog.margin = self.margin stop_loss = 0 for i, row in enumerate(self.ts.itertuples()): date = row.Index.to_pydatetime() high = row.high low = row.low close = row.close end_flag = pf.is_last_row(self.ts, i) shares = 0 # buy if (self.tlog.num_open_trades() < self.max_positions and row.regime > 0 and close == row.period_low and not end_flag): # calc number of shares buying_power = self.tlog.calc_buying_power(price=close) cash = buying_power / (self.max_positions - self.tlog.num_open_trades()) shares = self.tlog.calc_shares(price=close, cash=cash) # enter buy in trade log self.tlog.buy(date, close, shares) # set stop loss stop_loss = self.stop__loss_pct * close # sell elif (self.tlog.num_open_trades() > 0 and (close == row.period_high or low < stop_loss or end_flag)): # enter sell in trade log shares = self.tlog.sell(date, close) if shares > 0: pf.DBG("{0} BUY {1} {2} @ {3:.2f}".format( date, shares, self.symbol, close)) elif shares < 0: pf.DBG("{0} SELL {1} {2} @ {3:.2f} {4}".format( date, -shares, self.symbol, close, 'STOP' if low < stop_loss else '')) # record daily balance self.dbal.append(date, high, low, close)
def _algo(self): pf.TradeLog.cash = self.capital pf.TradeLog.margin = self.margin stop_loss = 0 for i, row in enumerate(self.ts.itertuples()): date = row.Index.to_pydatetime() high = row.high low = row.low close = row.close end_flag = pf.is_last_row(self.ts, i) shares = 0 # Sell Logic # First we check if an existing position in symbol should be sold # - sell if price closes at X day high # - sell if price closes below stop loss # - sell if end of data if self.tlog.shares > 0: if close == row.period_high or low < stop_loss or end_flag: if close < stop_loss: print('STOP LOSS!!!') shares = self.tlog.sell(date, close) # Buy Logic # First we check to see if there is an existing position, if so do nothing # - Buy if (regime > 0 or not use_regime_filter) # and price closes at X day low else: if (((row.regime > 0 or close > row.sma) or not self.use_regime_filter) and close == row.period_low): shares = self.tlog.buy(date, close) # set stop loss stop_loss = self.stop_loss_pct * close if shares > 0: pf.DBG("{0} BUY {1} {2} @ {3:.2f}".format( date, shares, self.symbol, close)) elif shares < 0: pf.DBG("{0} SELL {1} {2} @ {3:.2f} {4}".format( date, -shares, self.symbol, close, 'STOP' if low < stop_loss else '')) # record daily balance self.dbal.append(date, high, low, close)
def _algo(self): pf.TradeLog.cash = self.capital pf.TradeLog.margin = self.options['margin'] stop_loss = 0 for i, row in enumerate(self.ts.itertuples()): date = row.Index.to_pydatetime() high = row.high low = row.low close = row.close end_flag = pf.is_last_row(self.ts, i) max_open_trades = self.options['max_open_trades'] enable_scale_in = self.options['enable_scale_in'] enable_scale_out = self.options['enable_scale_out'] max_open_trades_buy = max_open_trades if enable_scale_in else 1 max_open_trades_sell = max_open_trades if enable_scale_out else 1 # Buy Logic # - Buy if still open trades slots left # and bull regime # and price closes at period low # and not end end_flag if (row.regime > 0 and close == row.period_low and not end_flag): # Get current, then set new weight weight = self.tlog.share_percent(close) weight += 1 / max_open_trades_buy * 100 weight = _round_weight(weight) self.tlog.adjust_percent(date, close, weight) # Sell Logic # First we check if we have any open trades, then # - Sell if price closes at X day high. # - Sell if price closes below stop loss. # - Sell if end of data. elif (self.tlog.shares > 0 and (close == row.period_high or low < stop_loss or end_flag)): # Get current, then set new weight weight = self.tlog.share_percent(close) weight -= 1 / max_open_trades_sell * 100 weight = _round_weight(weight) self.tlog.adjust_percent(date, close, weight) # Record daily balance. self.dbal.append(date, high, low, close)
def _algo(self): """ This is a general asset allocation stategy. Invest an equal percent in each investment option and rebalance every year. """ pf.TradeLog.cash = self.capital pf.TradeLog.margin = pf.Margin.CASH # These dicts are used to track close and weights for # each symbol in portfolio prices = {} weights = {} weight = 1 / len(self.portfolio.symbols) weights = {symbol: weight for symbol in self.portfolio.symbols} # Trading algorithm for i, row in enumerate(self.ts.itertuples()): date = row.Index.to_pydatetime() end_flag = pf.is_last_row(self.ts, i) start_flag = (i == 0) # Buy on first trading day # Rebalance on the first trading day of each year # Close all positions on last trading day if row.first_doty or end_flag or start_flag: # If last row, then zero out all weights. if end_flag: weights = pf.set_dict_values(weights, 0) # Get closing prices for all symbols p = self.portfolio.get_prices(row, fields=['close']) prices = { symbol: p[symbol]['close'] for symbol in self.portfolio.symbols } # Adjust weights of all symbols in portfolio self.portfolio.adjust_percents(date, prices, weights, row) # Record daily balance. self.portfolio.record_daily_balance(date, row)
def _algo(self): pf.TradeLog.cash = self.capital pf.TradeLog.margin = self.options['margin'] lookback = None for i, row in enumerate(self.ts.itertuples()): date = row.Index.to_pydatetime() high = row.high low = row.low close = row.close end_flag = pf.is_last_row(self.ts, i) # If lookback is None, then select a random lookback of # 6,7,8,...,or 12 months, if not in a position. if self.tlog.shares == 0: if self.options['lookback'] is None: lookback = random.choice(range(6, 12 + 1)) else: lookback = self.options['lookback'] #mom = getattr(row, 'mom'+str(lookback)) mom = self.tlog.get_price(row, 'mom' + str(lookback)) # Sell Logic # First we check if an existing position in symbol should be sold # - if first_dotw # sell if mom < 0 # sell if end_flag if self.tlog.shares > 0: if ((row.first_dotw and mom < 0) or end_flag): self.tlog.sell(date, close) # Buy Logic # - if first_dotw # buy if mom > 0 else: if (row.first_dotw and mom > 0): self.tlog.buy(date, close) # Record daily balance self.dbal.append(date, high, low, close)
def _algo(self): """ Use simple buy and hold strategy. """ pf.TradeLog.cash = self.capital pf.TradeLog.margin = pf.Margin.CASH for i, row in enumerate(self.ts.itertuples()): date = row.Index.to_pydatetime() end_flag = pf.is_last_row(self.ts, i) # Buy. if self.tlog.shares == 0: self.tlog.buy(date, row.close) # Sell. elif end_flag: self.tlog.sell(date, row.close) # Record daily balance. self.dbal.append(date, row.high, row.low, row.close)
def _algo(self): pf.TradeLog.cash = self.capital for i, row in enumerate(self.ts.itertuples()): date = row.Index.to_pydatetime() high = row.high low = row.low close = row.close end_flag = pf.is_last_row(self.ts, i) upper_band = row.sma * (1 + self.options['percent_band'] / 100) lower_band = row.sma * (1 - self.options['percent_band'] / 100) # Sell Logic # First we check if an existing position in symbol # should be sold # - Sell if (use_regime_filter and regime < 0) # - Sell if price closes below lower_band # - Sell if end of data if self.tlog.shares > 0: if ((self.options['use_regime_filter'] and row.regime < 0) or close < lower_band or end_flag): self.tlog.sell(date, close) # Buy Logic # First we check to see if there is an existing position, # if so do nothing # - Buy if (regime > 0 or not use_regime_filter) # and price closes above upper_band # and (use_regime_filter and regime > 0) else: if ((row.regime > 0 or not self.options['use_regime_filter']) and close > upper_band): self.tlog.buy(date, close) # Record daily balance self.dbal.append(date, high, low, close)
def _algo(self): pf.TradeLog.cash = self.capital for i, row in enumerate(self.ts.itertuples()): date = row.Index.to_pydatetime() high = row.high low = row.low close = row.close end_flag = pf.is_last_row(self.ts, i) # Buy if self.tlog.shares == 0: if row.regime > 0 and self.ts['regime'][i - 1] < 0: self.tlog.buy(date, close) # Sell else: if row.regime < 0 or end_flag: self.tlog.sell(date, close) # Record daily balance. self.dbal.append(date, high, low, close)
def _algo(self): pf.TradeLog.cash = self.capital pf.TradeLog.margin = self.options['margin'] stop_loss = 0 for i, row in enumerate(self.ts.itertuples()): date = row.Index.to_pydatetime() high = row.high; low = row.low; close = row.close end_flag = pf.is_last_row(self.ts, i) # Sell Logic # First we check if we have any shares, then # - Sell if price closes at X day high. # - Sell if price closes below stop loss. # - Sell if end of data. if self.tlog.shares > 0: if close == row.period_high or low < stop_loss or end_flag: if close < stop_loss: print('STOP LOSS!!!') self.tlog.sell(date, close) # Buy Logic # - Buy if (regime > 0 or close > row.sma) or not using regime filter) # and price closes at X day low. else: if (((row.regime > 0 or close > row.sma) or not self.options['use_regime_filter']) and close == row.period_low): self.tlog.buy(date, close) # Set stop loss. stop_loss = (1-self.options['stop_loss_pct'])*close # Record daily balance. self.dbal.append(date, high, low, close)
def _algo(self): pf.TradeLog.cash = self.capital pf.TradeLog.margin = self.options['margin'] # These dicts are used to track close, mom, and weights for # each symbol in portfolio prices = {} mom = {} weights = {} # A counter to countdown the number of months a lookback has # been in place month_count = 0 for i, row in enumerate(self.ts.itertuples()): date = row.Index.to_pydatetime() end_flag = pf.is_last_row(self.ts, i) if month_count == 0: # if period is None, then select a random trading period of # 6,7,8,...,or 12 months if self.options['lookback'] is None: lookback = random.choice(range(6, 12 + 1)) else: lookback = self.options['lookback'] month_count = lookback # If first day of the month or last row if row.first_dotm or end_flag: month_count -= 1 # Get prices for current row mom_field = 'mom' + str(lookback) p = self.portfolio.get_prices(row, fields=['close', mom_field]) # Copy data from `p` into prices and mom dicts for # convenience, also zero out weights dict. for symbol in self.portfolio.symbols: prices[symbol] = p[symbol]['close'] mom[symbol] = p[symbol][mom_field] weights[symbol] = 0 # Rebalance logic: # Assign weights using relative momentum # Then assign using absolute momentum if enabled # Finally rebalance # Set weights to zero if last row or using regime # filter and regime has turned bearish. if end_flag or (self.options['use_regime_filter'] and row.regime < 0): # Since weights dict is already zeroed out, all positions # will be closed out below with adjust_percent() pass else: # Relative momentum: Sort by highest momentum. mom = pf.sort_dict(mom, reverse=True) # Get the top tier momentum symbols; assign # equal weight to top tier symbols for i in range(self.options['top_tier']): symbol = list(mom.keys())[i] weights[symbol] = 1 / self.options['top_tier'] # Absolute momentum: Set weight to zero if percent # change is negative. if self.options['use_absolute_mom']: for symbol, pct_change in mom.items(): if pct_change < 0: weights[symbol] = 0 # Rebalance portfolio self.portfolio.adjust_percents(date, prices, weights, row) # record daily balance self.portfolio.record_daily_balance(date, row)
def _algo(self): pf.TradeLog.cash = self.capital pf.TradeLog.margin = self.options['margin'] # Create a stop_loss dict for each symbol. stop_loss = {symbol: 0 for symbol in self.portfolio.symbols} # stop loss pct should range between 0 and 1, user may have # expressed this as a percentage 0-100 if self.options['stop_loss_pct'] > 1: self.options['stop_loss_pct'] /= 100 period_high_field = 'period_high' + str(self.options['period']) period_low_field = 'period_low' + str(self.options['period']) # Loop though timeseries. for i, row in enumerate(self.ts.itertuples()): date = row.Index.to_pydatetime() end_flag = pf.is_last_row(self.ts, i) # Get the prices for this row, put in dict p. p = self.portfolio.get_prices(row, fields=[ 'close', 'regime', period_high_field, period_low_field, 'vola' ]) # Sum the inverse volatility for each row. inverse_vola_sum = 0 for symbol in self.portfolio.symbols: inverse_vola_sum += 1 / p[symbol]['vola'] # Loop though each symbol in portfolio. for symbol in self.portfolio.symbols: # Use variables to make code cleaner close = p[symbol]['close'] regime = p[symbol]['regime'] period_high = p[symbol][period_high_field] period_low = p[symbol][period_low_field] inverse_vola = 1 / p[symbol]['vola'] # Sell Logic # First we check if an existing position in symbol should be sold # - sell if price closes at X day high # - sell if price closes below stop loss # - sell if end of data by adjusted the percent to zero if symbol in self.portfolio.positions: if close == period_high or close < stop_loss[ symbol] or end_flag: if close < stop_loss[symbol]: print('STOP LOSS!!!') self.portfolio.adjust_percent(date, close, 0, symbol, row) # Buy Logic # First we check to see if there is an existing position, if so do nothing # - Buy if (regime > 0 or not use_regime_filter) and price closes at X day low else: if (regime > 0 or not self.options['use_regime_filter'] ) and close == period_low: # Use volatility weight. if self.options['use_vola_weight']: weight = inverse_vola / inverse_vola_sum # Use equal weight. else: weight = 1 / len(self.portfolio.symbols) self.portfolio.adjust_percent(date, close, weight, symbol, row) # Set stop loss stop_loss[symbol] = ( 1 - self.options['stop_loss_pct']) * close # record daily balance self.portfolio.record_daily_balance(date, row)
def _algo(self): """ Algo: - The future closes above its upper band, buy - The future closes below its lower band, sell your long position. """ pf.TradeLog.cash = self.capital pf.TradeLog.margin = self.margin pf.TradeLog.multiplier = self.multiplier stop_loss = 0 for i, row in enumerate(self.ts.itertuples()): date = row.Index.to_pydatetime() high = row.high low = row.low close = row.close end_flag = pf.is_last_row(self.ts, i) regime = row.regime vola = row.vola # this yahoo futures data hasn't been cleaned well. there are zero values in here. if end_flag: if self.tlog.shares > 0: self.tlog._exit_trade(date, close, shares=None, direction=self.tlog.direction) # Sell Logic # First we check if an existing position in symbol should be sold # - sell if price closes at X day low # - sell if price closes below stop loss elif regime < 0: if self.tlog.shares > 0: if self.tlog.direction == pf.Direction.LONG: # exit long trade; enter short trade self.tlog._exit_trade(date, close, direction=pf.Direction.LONG) if self.enable_shorts: cash = self.tlog.calc_buying_power(close) shares = self.tlog.calc_shares(close, cash=cash / self.multiplier) self.tlog._enter_trade( date, close, shares=shares, direction=pf.Direction.SHORT) stop_loss = (2 - self.stop_loss_pct) * close else: pass if self.enable_shorts: if close > stop_loss: print('STOP LOSS!!!') self.tlog._exit_trade( date, close, direction=pf.Direction.SHORT) else: if self.enable_shorts: # enter new short position cash = self.tlog.calc_buying_power(close) shares = self.tlog.calc_shares(close, cash=cash / self.multiplier) self.tlog._enter_trade(date, close, shares=shares, direction=pf.Direction.SHORT) # set stop loss stop_loss = (2 - self.stop_loss_pct) * close # Buy Logic # First we check if an existing position in symbol should be bought # - buy if price closes at X day high # - buy if price closes below stop loss elif regime > 0: if self.tlog.shares > 0: if self.tlog.direction == pf.Direction.SHORT: # exit short trade; enter long trade if self.enable_shorts: self.tlog._exit_trade(date, close, direction=pf.Direction.SHORT) cash = self.tlog.calc_buying_power(close) shares = self.tlog.calc_shares( close, cash=cash / self.multiplier * .30 / vola) self.tlog._enter_trade(date, close, shares=shares, direction=pf.Direction.LONG) stop_loss = self.stop_loss_pct * close else: if close < stop_loss: print('STOP LOSS!!!') self.tlog._exit_trade(date, close, direction=pf.Direction.LONG) else: # enter new long position cash = self.tlog.calc_buying_power(close) shares = self.tlog.calc_shares( close, cash=cash / self.multiplier * .30 / vola) self.tlog._enter_trade(date, close, shares=shares, direction=pf.Direction.LONG) # set stop loss stop_loss = self.stop_loss_pct * close # record daily balance self.dbal.append(date, high, low, close)
def _algo(self): pf.TradeLog.cash = self.capital pf.TradeLog.margin = self.margin close = {} mom = {} weights = {} cnt = 0 for i, row in enumerate(self.ts.itertuples()): date = row.Index.to_pydatetime() end_flag = pf.is_last_row(self.ts, i) if cnt == 0: # if period is None, then select a random trading period of # 6,7,8,...,or 12 months if self.lookback is None: lookback = random.choice(range(3, 12 + 1)) cnt = lookback else: lookback = self.lookback mom_field = 'mom' + str(lookback) p = self.portfolio.get_prices(row, fields=['close', mom_field]) if row.first_dotm or end_flag: # reverse sort by last weights (want current positions first in dict) weights = dict( sorted(weights.items(), key=lambda x: x[1], reverse=True)) for symbol in self.portfolio.symbols: close[symbol] = p[symbol]['close'] mom[symbol] = p[symbol][mom_field] weights[symbol] = 0 # Rebalance logic - assign weights using relative momentum # then assign using absolute momentum if enabled # finally rebalance # relative momentum if end_flag or (self.use_regime_filter and row.regime < 0): pass else: # sort by highest momentum mom = dict( sorted(mom.items(), key=lambda x: x[1], reverse=True)) l = list(mom) for i in range(self.top_tier): symbol = l[i] weights[symbol] = 1 / self.top_tier # absolute momentum if self.use_absolute_mom: for symbol, roc in mom.items(): if roc < 0: weights[symbol] = 0 # rebalance portfolio for symbol, weight in weights.items(): self.portfolio.adjust_percent(date, close[symbol], weights[symbol], symbol, row) if self.lookback is None: cnt -= 1 # record daily balance self.portfolio.record_daily_balance(date, row)
def _algo(self): pf.TradeLog.cash = self.capital pf.TradeLog.margin = self.options['margin'] # These dicts are used to track close, mom, and weights for # each symbol in portfolio prices = {} mom = {} weights = {} # These variables are assigned to the actual EFT US_STOCKS = self.symbols['US STOCKS'] US_BONDS = self.symbols['US BONDS'] EXUS_STOCKS = self.symbols['EX-US STOCKS'] TBILL = self.symbols['T-BILL'] # A counter to countdown the number of months a lookback has # been in place month_count = 0 for i, row in enumerate(self.ts.itertuples()): date = row.Index.to_pydatetime() end_flag = pf.is_last_row(self.ts, i) if month_count == 0: # if period is None, then select a random trading period of # 6,7,8,...,or 12 months if self.options['lookback'] is None: lookback = random.choice(range(6, 12 + 1)) else: lookback = self.options['lookback'] month_count = lookback # If first day of the month or last row if row.first_dotm or end_flag: month_count -= 1 # Get prices for current row mom_field = 'mom' + str(lookback) p = self.portfolio.get_prices(row, fields=['close', mom_field]) # Copy data from `p` into prices and mom dicts for # convenience, also zero out weights dict. for symbol in self.portfolio.symbols: prices[symbol] = p[symbol]['close'] mom[symbol] = p[symbol][mom_field] weights[symbol] = 0 # Rebalance logic: # Assign weights using relative momentum # Then assign using absolute momentum if enabled # Finally rebalance # GEM strategy if end_flag: # Since weights dict is zeroed out, all positions # will be closed out below with adjust_percent() pass elif mom[US_STOCKS] > mom[TBILL]: if mom[US_STOCKS] > mom[EXUS_STOCKS]: weights[US_STOCKS] = 1 else: weights[EXUS_STOCKS] = 1 else: weights[US_BONDS] = 1 # Rebalance portfolio self.portfolio.adjust_percents(date, prices, weights, row) # record daily balance self.portfolio.record_daily_balance(date, row)
def _algo(self): """ Algo: 1. The SPY is above its 200-day moving average 2. The SPY closes at a X-day low, buy with full capital. 3. If the SPY closes at a X-day high, sell some. If it sets further highs, sell some more, etc... 4. If you have free cash, use it all when fresh lows are set. """ pf.TradeLog.cash = self.capital pf.TradeLog.margin = self.margin stop_loss = 0 for i, row in enumerate(self.ts.itertuples()): date = row.Index.to_pydatetime() high = row.high low = row.low close = row.close end_flag = pf.is_last_row(self.ts, i) shares = 0 # buy if (self.tlog.num_open_trades() < self.max_positions and row.regime > 0 and close == row.period_low and not end_flag): # calc number of shares buying_power = self.tlog.calc_buying_power(price=close) shares = self.tlog.calc_shares(price=close, cash=buying_power) # if we have enough cash to buy any shares, then buy them if shares > 0: # enter buy in trade log self.tlog.buy(date, close, shares) # set stop loss stop_loss = 0 * close # set positions to max_positions self.positions = self.max_positions # sell elif (self.tlog.num_open_trades() > 0 and (close == row.period_high or low < stop_loss or end_flag)): if end_flag: shares = self.tlog.shares else: shares = int(self.tlog.shares / (self.positions)) self.positions -= 1 # enter sell in trade log shares = self.tlog.sell(date, close, shares) if shares > 0: pf.DBG("{0} BUY {1} {2} @ {3:.2f}".format( date, shares, self.symbol, close)) elif shares < 0: pf.DBG("{0} SELL {1} {2} @ {3:.2f}".format( date, -shares, self.symbol, close)) # record daily balance self.dbal.append(date, high, low, close)
def _algo(self): pf.TradeLog.cash = self.capital pf.TradeLog.margin = self.margin close = {} mom = {} weights = {} SP500 = self.symbols['SP500'] BONDS = self.symbols['BONDS'] EXUS = self.symbols['EXUS'] TBILL = self.symbols['T-BILL'] cnt = 0 for i, row in enumerate(self.ts.itertuples()): date = row.Index.to_pydatetime() end_flag = pf.is_last_row(self.ts, i) if cnt == 0: # if period is None, then select a random trading period of # 6,7,8,...,or 12 months if self.lookback is None: lookback = random.choice(range(3, 12 + 1)) cnt = lookback else: lookback = self.lookback mom_field = 'mom' + str(lookback) p = self.portfolio.get_prices(row, fields=['close', mom_field]) if row.first_dotm or end_flag: # reverse sort by last weights (want current positions first in dict) weights = dict( sorted(weights.items(), key=lambda x: x[1], reverse=True)) for symbol in self.portfolio.symbols: close[symbol] = p[symbol]['close'] mom[symbol] = p[symbol][mom_field] weights[symbol] = 0 # Rebalance logic - assign weights using relative momentum # then assign using absolute momentum if enabled # finally rebalance # relative momentum if end_flag: pass elif mom[SP500] > mom[TBILL]: if mom[SP500] > mom[EXUS]: weights[SP500] = 1 else: weights[EXUS] = 1 else: weights[BONDS] = 1 # absolute momentum if self.use_absolute_mom: if mom[SP500] < 0: weights[SP500] = 0 if mom[EXUS] < 0: weights[EXUS] = 0 if mom[BONDS] < 0: weights[BONDS] = 0 if mom[TBILL] < 0: weights[TBILL] = 0 # rebalance portfolio for symbol, weight in weights.items(): self.portfolio.adjust_percent(date, close[symbol], weights[symbol], symbol, row) if self.lookback is None: cnt -= 1 # record daily balance self.portfolio.record_daily_balance(date, row)
def _algo(self): """ Algo: 1. The SPY is higher than X days ago, buy 2. If the SPY is lower than X days ago, sell your long position. """ pf.TradeLog.cash = self.capital pf.TradeLog.margin = self.margin stop_loss = 0 for i, row in enumerate(self.ts.itertuples()): date = row.Index.to_pydatetime() high = row.high; low = row.low; close = row.close end_flag = pf.is_last_row(self.ts, i) shares = 0 if self.tlog.shares == 0: # if period is None, then select a random trading period of # 6,7,8,...,or 12 months if self.period is None: period = random.choice(range(6, 12+1)) else: period = self.period mom = getattr(row, 'mom'+str(period)) # Sell Logic # First we check if an existing position in symbol should be sold # - if first_dotm (or first_dotw) # sell if mom < 0 # sell if low < stop_loss # sell if end_flag if self.tlog.shares > 0: #if (row.first_dotm: if (row.first_dotw and (mom < 0 or low < stop_loss or end_flag)): # enter sell in trade log shares = self.tlog.sell(date, close) # Buy Logic # - if first_dotm (or first_dotw) # buy if mom > 0 else: #if (row.first_dotm if (row.first_dotw and mom > 0): # enter buy in trade log shares = self.tlog.buy(date, close) # set stop loss stop_loss = 0*close if shares > 0: pf.DBG("{0} BUY {1} {2} @ {3:.2f}".format( date, shares, self.symbol, close)) elif shares < 0: pf.DBG("{0} SELL {1} {2} @ {3:.2f}".format( date, -shares, self.symbol, close)) # record daily balance self.dbal.append(date, high, low, close)
def _algo(self): pf.TradeLog.cash = self.capital pf.TradeLog.margin = self.options['margin'] stop_loss = 0 for i, row in enumerate(self.ts.itertuples()): date = row.Index.to_pydatetime() high = row.high; low = row.low; close = row.close; end_flag = pf.is_last_row(self.ts, i) shares = 0 max_open_trades = self.options['max_open_trades'] enable_scale_in = self.options['enable_scale_in'] enable_scale_out = self.options['enable_scale_out'] max_open_trades_buy = max_open_trades if enable_scale_in else 1 num_open_trades = self.tlog.num_open_trades # Buy Logic # - Buy if still open trades slots left # and bull regime # and price closes at period low # and not end end_flag if (num_open_trades < max_open_trades_buy and row.regime > 0 and close == row.period_low and not end_flag): # Calc number of shares for another cash-equal trade. buying_power = self.tlog.calc_buying_power(close) cash = buying_power / (max_open_trades_buy - num_open_trades) shares = self.tlog.calc_shares(close, cash) # Buy more shares if we have the cash. if shares > 0: # Enter buy in trade log self.tlog.buy(date, close, shares) # Set stop loss stop_loss = (1-self.options['stop_loss_pct'])*close # set sell_parts to max_open_trades num_out_trades = max_open_trades # Sell Logic # First we check if we have any open trades, then # - Sell if price closes at X day high. # - Sell if price closes below stop loss. # - Sell if end of data. elif (num_open_trades > 0 and (close == row.period_high or low < stop_loss or end_flag)): if not enable_scale_out or low < stop_loss or end_flag: # Exit all positions. shares = None elif enable_scale_in: # Exit one position. shares = -1 else: # Scaling out is done here by shares, for example # if there are 100 shares and num trades is 4, # then we reduce by 25 each time. This is # different than scaling out by percentage of # total fund value as is done in strategy.py. shares = int(self.tlog.shares / num_out_trades) num_out_trades -= 1 # Enter sell in trade log. shares = self.tlog.sell(date, close, shares) if shares > 0: pf.DBG("{0} BUY {1} {2} @ {3:.2f}".format( date, shares, self.symbol, close)) elif shares < 0: pf.DBG("{0} SELL {1} {2} @ {3:.2f}".format( date, -shares, self.symbol, close)) # Record daily balance. self.dbal.append(date, high, low, close)
def _algo(self): pf.TradeLog.cash = self.capital pf.TradeLog.margin = self.margin stop_loss = {symbol: 0 for symbol in self.portfolio.symbols} period_high_field = 'period_high' + str(self.period) period_low_field = 'period_low' + str(self.period) for i, row in enumerate(self.ts.itertuples()): date = row.Index.to_pydatetime() end_flag = pf.is_last_row(self.ts, i) p = self.portfolio.get_prices(row, fields=[ 'close', 'regime', period_high_field, period_low_field, 'vola' ]) # need to sum the inverse volatility for each row inverse_vola_sum = 0 for symbol in self.portfolio.symbols: inverse_vola_sum += 1 / p[symbol]['vola'] # get symbol row data for symbol in self.portfolio.symbols: close = p[symbol]['close'] regime = p[symbol]['regime'] period_high = p[symbol][period_high_field] period_low = p[symbol][period_low_field] inverse_vola = 1 / p[symbol]['vola'] # Sell Logic # First we check if an existing position in symbol should be sold # - sell if price closes at X day high # - sell if price closes below stop loss # - sell if end of data if symbol in self.portfolio.positions(): if close == period_high or close < stop_loss[ symbol] or end_flag: if close < stop_loss[symbol]: print('STOP LOSS!!!') self.portfolio.adjust_percent(date, close, 0, symbol, row) # Buy Logic # First we check to see if there is an existing position, if so do nothing # - Buy if (regime > 0 or not use_regime_filter) and price closes at X day low else: if (regime > 0 or not self.use_regime_filter ) and close == period_low: # use volatility weight if self.use_vola_weight: weight = inverse_vola / inverse_vola_sum # use equal weight else: weight = 1 / len(self.portfolio.symbols) self.portfolio.adjust_percent(date, close, weight, symbol, row) # set stop loss stop_loss[symbol] = self.stop_loss_pct * close # record daily balance self.portfolio.record_daily_balance(date, row)