def maybe_invest(api: tradeapi.REST) -> None: target_symbols = ['AAPL', 'VOO'] user_context = UserContext() user_context.set_account(api.get_account()) stock_context_list = [ StockContext(target_symbol) for target_symbol in target_symbols ] # Populate stock context list for potential investment. for stock_context in stock_context_list: last_trade = api.get_last_trade(stock_context.symbol) stock_context.set_last_trade(last_trade) # Filter out a list of stocks that should be considered # for investment at the moment. stock_feasibility_checker = StockFeasibilityChecker(user_context) filtered_stock_context_list = filter(stock_feasibility_checker, stock_context_list) # Rank the potential list of stocks to invest based on # the potential growth. stock_comparator = StockComparator(user_context) ranked_stock_context_list = sorted(filtered_stock_context_list, key=stock_comparator) # Send order to invest if fund is sufficient stock_action_executor = StockActionExecutor(user_context) for ranked_stock_context in ranked_stock_context_list: stock_action_executor(ranked_stock_context)
def __init__(self, paper=True): key_names = Settings.keys_names if paper: key_id = key_names["Alpaca Paper Key ID"] secret_key = key_names["Alpaca Paper Secret Key"] base_url = "https://paper-api.alpaca.markets" else: key_id = key_names["Alpaca Live Key ID"] secret_key = key_names["Alpaca Live Secret Key"] base_url = "https://api.alpaca.markets" key_id = environ[key_id] secret_key = environ[secret_key] self.api = REST(key_id, secret_key, base_url) del key_id, secret_key
def get_data_alpaca(parameters): dividends = None splits = None api = REST(alpaca_keys.APCA_API_KEY_ID, alpaca_keys.APCA_API_SECRET_KEY) data = api.get_aggs(parameters['symbol'], multiplier=parameters['multiplier'], timespan=parameters['timespan'], _from=parameters['_from'], to=parameters['to']).df if parameters['timestamp_type'] == 'date': dividends, splits = get_actions_alpaca(parameters['symbol']) return create_tuple_alpaca(data, parameters['timestamp_type'], dividends=dividends, splits=splits)
class AlpacaAccount: def __init__(self, paper=True): key_names = Settings.keys_names if paper: key_id = key_names["Alpaca Paper Key ID"] secret_key = key_names["Alpaca Paper Secret Key"] base_url = "https://paper-api.alpaca.markets" else: key_id = key_names["Alpaca Live Key ID"] secret_key = key_names["Alpaca Live Secret Key"] base_url = "https://api.alpaca.markets" key_id = environ[key_id] secret_key = environ[secret_key] self.api = REST(key_id, secret_key, base_url) del key_id, secret_key def get_api(self): return self.api def list_assets(self, shortable=False, fractionable=False, show_names=False): active_assets = self.api.list_assets(status='active') myfilter = [] if shortable and fractionable: for asset in active_assets: if asset.easy_to_borrow and asset.marginable and asset.fractionable: myfilter.append(asset) elif shortable: for asset in active_assets: if asset.easy_to_borrow and asset.marginable: myfilter.append(asset) elif fractionable: for asset in active_assets: if asset.fractionable: myfilter.append(asset) else: myfilter = active_assets if show_names: return [f"{i.name} :: '{i.symbol}'" for i in myfilter] else: return [i.symbol for i in myfilter]
class TickerFilter: def __init__(self, key, secret): self.api = Alpaca(key, secret, 'https://paper-api.alpaca.markets') self.cached_tickers = {} def ticker_exists(self, ticker): try: if ticker in self.cached_tickers: return self.cached_tickers[ticker] asset = self.api.get_asset(ticker) self.cached_tickers[ticker] = asset.tradable return asset.tradable except: self.cached_tickers[ticker] = False return False def filter_pass(self, comment): words = alnum.sub('', comment).split() tickers = [word for word in words if word.isupper() and len(word) in RedditSentimentSource._VALID_TICKER_LENGTHS] for word in words: if self.ticker_exists(word): return True return False
def __init__(self, account: Account, base_url: str): super().__init__() self.client = REST(key_id=account.get_access_key(), secret_key=account.get_secret_key(), base_url=URL(base_url))
def select_swing_stocks(date: datetime, position_data: Dict, portfolio_amount: float): # Get Alpaca API key and secret storage_client = storage.Client() bucket = storage_client.get_bucket('derek-algo-trading-bucket') blob = bucket.blob('alpaca-api-key.txt') api_key = blob.download_as_text() blob = bucket.blob('alpaca-secret-key.txt') secret_key = blob.download_as_text() base_url = 'https://paper-api.alpaca.markets' api = REST(api_key, secret_key, base_url, 'v2') # Get all stocks assets = api.list_assets('active') symbols = [asset.symbol for asset in assets if asset.tradable] # Display currently held positions if position_data: print('Current positions:') else: print('No current positions') position_symbols = list(position_data.keys()) for symbol in position_symbols: current_price = float(position_data[symbol]['current_price']) entry_price = float(position_data[symbol]['avg_entry_price']) current_percent = (current_price - entry_price) / entry_price * 100 print('{}: {}%'.format(symbol, '%.2f' % current_percent)) # Get past 1000 days data for all stocks data = {} print(f'Retrieving {len(symbols)} symbol data...') symbols_chunked = list(chunks(list(set(symbols)), 200)) previous_day = datetime.isoformat(pd.Timestamp(date - timedelta(days=1))) for symbol_group in symbols_chunked: data_group = api.get_barset(','.join(symbol_group), '1D', end=previous_day, limit=1000).df for symbol in symbol_group: data[symbol] = data_group[symbol] buy_df = pd.DataFrame() sell_df = pd.DataFrame() hold_df = pd.DataFrame() # c = 0 print('Processing daily bars for all stocks...') for symbol in data.keys(): df = pd.DataFrame(data[symbol]) df = df.loc[df['close'] > 0] if symbol not in position_symbols and len(df) >= 1000: df['symbol'] = symbol df['bullish'] = pattern.detect_bullish_patterns(df) buy_df = buy_df.append(df.loc[df.index == df.index.max()]) elif symbol in position_symbols: df['symbol'] = symbol df['qty'] = int(position_data[symbol]['qty']) df['market_value'] = float(position_data[symbol]['market_value']) latest_rsi = rsi(df).df.tail(1)['rsi'][0] latest_cci = cci(df).df.tail(1)['cci'][0] purchase_price = float(position_data[symbol]['avg_entry_price']) latest_price = float(position_data[symbol]['current_price']) df['purchase_price'] = purchase_price df['latest_price'] = latest_price change_pct = (latest_price - purchase_price) / purchase_price * 100 print(f'\nHolding {symbol}: {round(change_pct, 2)}%') # If it has dropped below the stop loss percentage, GET IT OUT if change_pct <= -3: print(f'Price is below stop loss: SELL') sell_df = sell_df.append(df.loc[df.index == df.index.max()]) elif change_pct < 0 and (latest_rsi >= 70 or latest_cci >= 100): print(f'Overbought, RSI={round(latest_rsi, 0)}, CCI={round(latest_cci, 0)}: SELL') sell_df = sell_df.append(df.loc[df.index == df.index.max()]) # If price is at/above entry # Check if the swing is still swinging else: print(f'Price ${latest_price} is near/above entry ${purchase_price}') obv_df = obv(df).df obv_df['obv_ema'] = obv_df['obv'].ewm(span=20).mean() # Is the OBV still above it's EMA if obv_df.tail(1)['obv'][0] > obv_df.tail(1)['obv_ema'][0]: print('OBV is still above OBV_EMA') slope = linregress( [0, 1, 2], obv_df.tail(3)['obv'].tolist() ).slope if slope > 0: print(f'OBV is increasing with a slope of {slope}: HOLD') hold_df = hold_df.append(df.loc[df.index == df.index.max()]) else: print('OBV is above EMA but not increasing: SELL') sell_df = sell_df.append(df.loc[df.index == df.index.max()]) else: print('OBV is no longer above EMA: SELL') sell_df = sell_df.append(df.loc[df.index == df.index.max()]) print() # c += 1 # if c % 100 == 0: # print(f'{c}/{len(data.keys())}') # print(f'{c}/{len(data.keys())}\n') # END SCREENING SECTION # Consolidate results # hold_stocks = hold_df.loc[hold_df.index == hold_df.index.max()] # sell_stocks = sell_df.loc[sell_df.index == sell_df.index.max()] portfolio_size = 20 purchase_size = portfolio_size - len(hold_df) # If there's room in the portfolio to buy more if purchase_size > 0: print(f'We can purchase {purchase_size} new stocks today.') # buy_stocks = buy_df.loc[buy_df.index == buy_df.index.max()] buy_stocks = buy_df[buy_df['bullish'] != ''] buy_stocks = buy_stocks.sort_values(by='volume', ascending=False).head(purchase_size) holding_value = sum(hold_df['market_value'].tolist()) if not hold_df.empty else 0.0 available_funds = portfolio_amount - holding_value print(f'Available funds to buy: ${available_funds}') # For now this will create equal-weight positions funds_per_stock = available_funds / len(buy_stocks) # Calculate quantity to buy for each stock buy_qty = [] symbols = buy_stocks['symbol'].tolist() prices = buy_stocks['close'].tolist() for i in range(0, len(symbols)): price = prices[i] qty = math.floor(funds_per_stock / price) buy_qty.append(qty) buy_stocks['qty'] = buy_qty buy_stocks['market_value'] = buy_stocks['close'] * buy_stocks['qty'] else: print('There is no room to buy.') buy_stocks = pd.DataFrame() return (buy_stocks, sell_df, hold_df)
def select_swing_stocks(): # Get Alpaca API key and secret storage_client = storage.Client() bucket = storage_client.get_bucket('derek-algo-trading-bucket') blob = bucket.blob('alpaca-api-key.txt') api_key = blob.download_as_text() blob = bucket.blob('alpaca-secret-key.txt') secret_key = blob.download_as_text() base_url = 'https://paper-api.alpaca.markets' api = REST(api_key, secret_key, base_url, 'v2') # Get all stocks assets = api.list_assets('active') symbols = [asset.symbol for asset in assets if asset.tradable] # Get all currently held positions positions = api.list_positions() if positions: print('Current positions:') position_symbols = [position.symbol for position in positions] position_data = {} for position in positions: current_percent = (float(position.current_price) - float(position.avg_entry_price)) \ / float(position.avg_entry_price) * 100 print('{}: {}%'.format(position.symbol, '%.2f' % current_percent)) position_data[position.symbol] = position print() # Get past 50 days data for all stocks data = {} symbols_chunked = list(chunks(list(set(symbols)), 200)) for symbol_group in symbols_chunked: print(f'Retrieving {len(symbol_group)} symbol data') data_group = api.get_barset(','.join(symbol_group), '1D', limit=1000).df for symbol in symbol_group: data[symbol] = data_group[symbol] buy_df = pd.DataFrame() sell_df = pd.DataFrame() hold_df = pd.DataFrame() c = 0 for symbol in data.keys(): df = pd.DataFrame(data[symbol]) df = df.loc[df['close'] > 0] if symbol not in position_symbols and len(df) == 1000: df['symbol'] = symbol # bullish pattern detection # bullish = [''] * len(df) # bullish[len(bullish) - 1] = pattern.detect_bullish_patterns(df) df['bullish'] = pattern.detect_bullish_patterns(df) buy_df = buy_df.append(df.loc[df.index == df.index.max()]) elif symbol in position_symbols: print(f'\nCurrently holding {symbol}:') df['symbol'] = symbol df['qty'] = int(position_data[symbol].qty) df['market_value'] = float(position_data[symbol].market_value) latest_rsi = rsi(df).df.tail(1)['rsi'][0] latest_cci = cci(df).df.tail(1)['cci'][0] purchase_price = float(position_data[symbol].avg_entry_price) latest_price = float(position_data[symbol].current_price) df['purchase_price'] = purchase_price df['latest_price'] = latest_price # If it has dropped below the entry price, GET IT OUT if latest_price < purchase_price: print( f'Price ${latest_price} is below entry ${purchase_price}: SELL' ) sell_df = sell_df.append(df.loc[df.index == df.index.max()]) # Or if the RSI or CCI are too high, GET IT OUT elif latest_rsi >= 70 or latest_cci >= 100: print(f'Overbought, RSI={latest_rsi}, CCI={latest_cci}: SELL') sell_df = sell_df.append(df.loc[df.index == df.index.max()]) # If price is at/above entry # Check if the swing is still swinging elif latest_price >= purchase_price: print( f'Price ${latest_price} is at/above entry ${purchase_price}' ) obv_df = obv(df).df obv_df['obv_ema'] = obv_df['obv'].ewm(span=20).mean() # Is the OBV still above it's EMA if obv_df.tail(1)['obv'][0] > obv_df.tail(1)['obv_ema'][0]: print('OBV is still above OBV_EMA') slope = linregress([0, 1, 2], obv_df.tail(3)['obv'].tolist()).slope if slope > 0: print( f'OBV is increasing with a slope of {slope}: HOLD') hold_df = hold_df.append( df.loc[df.index == df.index.max()]) print() c += 1 if c % 100 == 0: print(f'{c}/{len(data.keys())}') print(f'{c}/{len(data.keys())}\n') # END SCREENING SECTION # Consolidate results print('DECISION:\n') hold_stocks = hold_df.loc[hold_df.index == hold_df.index.max()] if not hold_stocks.empty: print(f'Hold {len(hold_stocks)}:\n' + '\n'.join(hold_stocks['symbol'].tolist()) + '\n') sell_stocks = sell_df.loc[sell_df.index == sell_df.index.max()] if not sell_stocks.empty: print(f'Sell {len(sell_stocks)}:\n' + '\n'.join(sell_stocks['symbol'].tolist()) + '\n') portfolio_size = 20 purchase_size = portfolio_size - len(hold_stocks) # If there's room in the portfolio to buy more if purchase_size > 0: print(f'We can purchase {purchase_size} new stocks today.') buy_stocks = buy_df.loc[buy_df.index == buy_df.index.max()] buy_stocks = buy_stocks[buy_stocks['bullish'] != ''] buy_stocks = buy_stocks.sort_values( by='volume', ascending=False).head(purchase_size) account = api.get_account() holding_value = hold_stocks['market_value'].tolist().sum( ) if not hold_stocks.empty else 0.0 available_funds = (float(account.portfolio_value) + float(account.cash) - holding_value) * 0.95 print(f'Available funds to buy: ${available_funds}') # For now this will create equal-weight positions funds_per_stock = available_funds / len(buy_stocks) # Calculate quantity to buy for each stock buy_qty = [] symbols = buy_stocks['symbol'].tolist() prices = buy_stocks['close'].tolist() for i in range(0, len(symbols)): price = prices[i] qty = math.floor(funds_per_stock / price) buy_qty.append(qty) buy_stocks['qty'] = buy_qty buy_stocks['market_value'] = buy_stocks['close'] * buy_stocks['qty'] print(f'Buy {len(buy_stocks)}:') print(buy_stocks) else: print('There is no room to buy.') buy_stocks = pd.DataFrame() return (buy_stocks, sell_stocks, hold_stocks)
from datetime import datetime from google.cloud import storage import pandas as pd pd.set_option('mode.chained_assignment', None) from alpaca_trade_api import REST from select_historic_swing_stocks import select_swing_stocks # Get Alpaca API key and secret storage_client = storage.Client() bucket = storage_client.get_bucket('derek-algo-trading-bucket') blob = bucket.blob('alpaca-api-key.txt') api_key = blob.download_as_text() blob = bucket.blob('alpaca-secret-key.txt') secret_key = blob.download_as_text() base_url = 'https://paper-api.alpaca.markets' api = REST(api_key, secret_key, base_url, 'v2') nyc = timezone('America/New_York') def get_open_price(date: datetime, symbol: Text): today = datetime.isoformat(pd.Timestamp(date)) bar = api.get_barset(symbol, '1D', start=today, end=today, limit=1).df return bar[symbol]['open'][bar.index.max()] def buy_stock(date: datetime, symbol: Text, qty: int): buy_price = get_open_price(date, symbol) position_data[symbol] = { 'qty': str(qty), 'avg_entry_price': str(buy_price),
def all_alpaca_assets(client: alpaca_trade_api.REST) -> list: return [_.symbol for _ in client.list_assets()]
def __init__(self, key, secret): self.api = Alpaca(key, secret, 'https://paper-api.alpaca.markets') self.cached_tickers = {}
import time from google.cloud import storage import pandas as pd pd.set_option('mode.chained_assignment', None) from alpaca_trade_api import REST import discord_webhook # Get Alpaca API key and secret storage_client = storage.Client() bucket = storage_client.get_bucket('derek-algo-trading-bucket') blob = bucket.blob('alpaca-api-key.txt') api_key = blob.download_as_text() blob = bucket.blob('alpaca-secret-key.txt') secret_key = blob.download_as_text() base_url = 'https://paper-api.alpaca.markets' api = REST(api_key, secret_key, base_url, 'v2') positions = api.list_positions() alert = '**End of Week Liquidations**\n\n**Sell**\n' # Market sell every position for position in positions: symbol = position.symbol qty = position.qty price = position.current_price api.submit_order( symbol=symbol, qty=str(qty), side='sell', type='limit', limit_price=str(price), time_in_force='day' ) alert += f'{symbol}: {qty}\n'
from google.cloud import storage import pandas as pd pd.set_option('mode.chained_assignment', None) from alpaca_trade_api import REST from select_swing_stocks import select_swing_stocks import discord_webhook # Get Alpaca API key and secret storage_client = storage.Client() bucket = storage_client.get_bucket('derek-algo-trading-bucket') blob = bucket.blob('alpaca-api-key.txt') api_key = blob.download_as_text() blob = bucket.blob('alpaca-secret-key.txt') secret_key = blob.download_as_text() base_url = 'https://paper-api.alpaca.markets' api = REST(api_key, secret_key, base_url, 'v2') # Check if the market is open today nyc = timezone('America/New_York') today = datetime.today().astimezone(nyc) today_str = today.strftime('%Y-%m-%d') today = datetime.isoformat(pd.Timestamp(datetime.today().astimezone(nyc))) try: calendar = api.get_calendar(start=today, end=today)[0] except Exception as e: print(e) print('Market must not be open') calendar = None if calendar and calendar.date.strftime('%Y-%m-%d') == today_str: # Select the swing stocks to buy, sell, and hold
from google.cloud import storage import pandas as pd pd.set_option('mode.chained_assignment', None) from alpaca_trade_api import REST import discord_webhook import statistics as stats # Get Alpaca API key and secret storage_client = storage.Client() bucket = storage_client.get_bucket('derek-algo-trading-bucket') blob = bucket.blob('alpaca-api-key.txt') api_key = blob.download_as_text() blob = bucket.blob('alpaca-secret-key.txt') secret_key = blob.download_as_text() base_url = 'https://paper-api.alpaca.markets' api = REST(api_key, secret_key, base_url, 'v2') # Retrieve all trade activities for the week today = datetime.today() monday = today - timedelta(days=4) today_str = f'{today.date()}T23:59:59Z' monday_str = f'{monday.date()}T00:00:00Z' print(f'Results from {monday_str} to {today_str}') activities = api.get_activities(activity_types='FILL', after=monday_str, until=today_str) # Retrieve all currently owned symbols positions = api.list_positions() owned_symbols = [position.symbol for position in positions]
class AlpacaExchange(Exchange): client: REST access_key: str secret_key: str @staticmethod def build(account: Account, is_paper=False): base_url_live = "https://api.alpaca.markets" base_url_paper = "https://paper-api.alpaca.markets" return AlpacaExchange( account=account, base_url=base_url_paper if is_paper else base_url_live) def __init__(self, account: Account, base_url: str): super().__init__() self.client = REST(key_id=account.get_access_key(), secret_key=account.get_secret_key(), base_url=URL(base_url)) def get_day_candles(self, ticker: str, start: str, end: str) -> List[Candle]: pass def get_last_candle(self, ticker: str) -> Candle: snapshot = self.client.get_snapshot(symbol=ticker) return BarAdapter(ticker=ticker, bar=snapshot.minute_bar) def get_all_assets(self) -> List[Asset]: account = self.client.get_account() positions = self.client.list_positions() cash = AccountAdapter(account.__dict__.get('_raw')) stocks = [ PositionAdapter(position.__dict__.get('_raw')) for position in positions ] return [cash, *stocks] def buy(self, ticker: str, amount: Decimal) -> Optional[Order]: return self.__order(side="buy", ticker=ticker, amount=amount) def sell(self, ticker: str, volume: Decimal) -> Optional[Order]: return self.__order(side="sell", ticker=ticker, volume=volume) def get_order(self, order_id: str) -> Optional[Order]: order = self.client.get_order_by_client_order_id( client_order_id=order_id) return OrderAdapter(AlpacaOrder(**order.__dict__.get("_raw"))) def __order(self, side: str, ticker: str, amount: Decimal = None, volume: Decimal = None) -> Optional[Order]: if amount is None and volume is None: raise ValueError("order amount or volume should not be None") if not self.__is_open_now(): return None custom_order_id = str(uuid.uuid4()) qty = float(volume) if volume is not None else None notional = float(amount) if amount is not None else None order = self.client.submit_order(symbol=ticker, qty=qty, notional=notional, side=side, type="market", client_order_id=custom_order_id) return OrderAdapter(AlpacaOrder(**order.__dict__.get("_raw"))) def __is_open_now(self): """check if US exchanges (NYSE, NASDAQ, etc) are open 09:30 (EST) ~ 16:00 (EST) """ clock = self.client.get_clock() return clock.is_open
def select_day_trade_stocks(event, context): # Get Alpaca API key and secret storage_client = storage.Client() bucket = storage_client.get_bucket('derek-algo-trading-bucket') blob = bucket.blob('alpaca-api-key.txt') api_key = blob.download_as_text() blob = bucket.blob('alpaca-secret-key.txt') secret_key = blob.download_as_text() base_url = 'https://paper-api.alpaca.markets' api = REST(api_key, secret_key, base_url, 'v2') # Get all stocks assets = api.list_assets('active') symbols = [asset.symbol for asset in assets if asset.tradable] # Get past 50 days data for all stocks data = {} symbols_chunked = list(chunks(list(set(symbols)), 200)) for symbol_group in symbols_chunked: print(f'Retrieving {len(symbol_group)} symbol data') data_group = api.get_barset(','.join(symbol_group), '1D', limit=50).df for symbol in symbol_group: data[symbol] = data_group[symbol] result_df = pd.DataFrame() for symbol in data.keys(): df = data[symbol] df = df.loc[df['close'] > 0] if len(df.index) >= 50: # Calculate day change percent dayChange = [] for i in df.index: try: high = df['high'][i] low = df['low'][i] if low and low > 0: dayChange.append(round(((high - low) / low) * 100, 2)) else: dayChange.append(0) except KeyError: dayChange.append(0) # Calculate averages df['dayChange'] = dayChange df['averageDayChange10'] = df['dayChange'].ewm(span=10).mean() df['averageVolume50'] = df['volume'].ewm(span=50).mean() df['averageVolume10'] = df['volume'].ewm(span=10).mean() df['symbol'] = symbol # Add most recent row i = len(df.index) - 1 result_df = result_df.append(df.iloc[i]) # Filter stocks by high volatility criteria filtered_df = result_df.query( 'averageDayChange10>4.5 & averageVolume50>4000000 & averageVolume10>4000000 & close>=5' ) # Sort descending by averageDayChange10 sorted_df = filtered_df.sort_values('averageDayChange10', ascending=False) # Grab top 5 stocks selected_stocks = sorted_df[:5] print(selected_stocks) symbols = list(selected_stocks['symbol'].values) print(symbols) # Store them in Alpaca watchlist watchlist = api.get_watchlist_by_name('day-trade-stocks') api.update_watchlist(watchlist.id, symbols=symbols) print('Success')
def get_actions_alpaca(symbol): api = REST(alpaca_keys.APCA_API_KEY_ID, alpaca_keys.APCA_API_SECRET_KEY) dividend_data = api.polygon.dividends(symbol) split_data = api.polygon.splits(symbol) return create_dict_actions(dividend_data, split_data)
from datetime import datetime, timedelta from time import time from typing import Dict from btalib.indicators.cci import cci from btalib.indicators.obv import obv from btalib.indicators.rsi import rsi from google.cloud import storage import math import pandas as pd pd.set_option('mode.chained_assignment', None) from alpaca_trade_api import REST from scipy.stats import linregress import detect_pattern as pattern # Get Alpaca API key and secret storage_client = storage.Client() bucket = storage_client.get_bucket('derek-algo-trading-bucket') blob = bucket.blob('alpaca-api-key.txt') api_key = blob.download_as_text() blob = bucket.blob('alpaca-secret-key.txt') secret_key = blob.download_as_text() base_url = 'https://paper-api.alpaca.markets' api = REST(api_key, secret_key, base_url, 'v2') bars = api.get_barset('AAPL', '1D', 5)['AAPL'] print(bars)
class AlpacaTradeInterface(TradeInterface): def __init__(self, key, secret, endpoint): self.api = Alpaca(key, secret, endpoint) self.pending_orders = {} self.cached_tickers = {} def initialize(self, env: Environment): try: # Load cash balance account = self.api.get_account() env.get_portfolio().cash = float( account.cash) # We have margin but shouldn't use it # Load open orders orders = self.api.list_orders(status='open', limit=500) self.pending_orders = { order.id: Order(order.symbol, OrderType(order.order_type), order.qty, order.side == 'buy', order_id=order.id, limit_price=order.limit_price, stop_price=order.stop_price) for order in orders } # Load open positions positions = self.api.list_positions() for pos in positions: env.get_portfolio()._add_position( Position(pos.symbol, pos.qty, pos.avg_entry_price, pos.current_price)) except Exception: logger.exception('Failed to pull current orders and cash balance') return False return True def update(self, env: Environment): orders = self.api.list_orders(status='closed', after=datetime.now() - timedelta(days=2), limit=500) for order in orders: if order.id in self.pending_orders: logger.info(f'Order {order.id} executed') env.notify_order_completed( ExecutedOrder(order.symbol, order.filled_qty, order.filled_avg_price, order.side == 'buy')) def place_order(self, order: Order): logger.info(f'Placing order for {order.quantity} {order.ticker}') try: result = self.api.submit_order(order.ticker, order.quantity, 'buy' if order.is_buy else 'sell', order.order_type.value, 'day', limit_price=order.limit_price, stop_price=order.stop_price) order.order_id = result.id self.pending_orders[result.id] = order return True except Exception: logger.exception( f'Failed to place order for {order.quantity} {order.ticker}') return False def cancel_order(self, order_id): logger.info(f'Canceling order {order_id}') try: self.api.cancel_order(order_id) self.pending_orders.pop(order_id, None) return True except Exception: logger.exception(f'Failed to cancel order {order_id}') return False def market_open(self): clock = self.api.get_clock() return clock.is_open # TODO - we also have open/close times. May want to avoid holding overnight def open_orders(self): return [order for order in self.pending_orders.values()] def ticker_exists(self, ticker): try: if ticker in self.cached_tickers: return self.cached_tickers[ticker] asset = self.api.get_asset(ticker) self.cached_tickers[ticker] = asset.tradable return asset.tradable except: self.cached_tickers[ticker] = False return False
import os import alpaca_trade_api as tradeapi import pandas as pd from datetime import datetime from alpaca_trade_api import REST os.environ['APCA_API_KEY_ID'] = 'AKYKO5J4G4C4S1SECH81' os.environ['APCA_API_SECRET_KEY'] = 'jj4D0a9jWLO8t6vDiF7DM1jCzaFRO5bnbfEHevDH' api = REST() start = pd.Timestamp(2004, 6, 10, 12).isoformat() end = pd.Timestamp(2005, 6, 23, 12).isoformat() # print(api.polygon.historic_agg_v2('AAPL', 1, 'minute', _from=start, to=end).df) # print(api.polygon.dividends('AAPL')[0]._raw) # print(api.polygon.splits('TXG')[0]._raw) data = api.get_aggs('SPY', 1, 'day', '1900-01-01', '2020-01-20') for i, record in data.df.iterrows(): timestamp = i.to_pydatetime() print(timestamp) break # print(api.get_aggs('GRPN',1,'day','2020-06-05','2020-06-13')) # data = api.get_aggs(parameters['symbol'], # multiplier=parameters['multiplier'], # timespan=parameter['timespan'], # _from=parameters['_from'], # to=parameters['to']).df # thing = api.get_aggs('ABT',1,'minute','2000-01-01','2100-01-01').df # print(thing.columns) # print(thing.index[0]) # print(thing.index[len(thing) - 1]) # print(datetime.fromtimestamp(thing.df.columns))
def __init__(self, key, secret, endpoint): self.api = Alpaca(key, secret, endpoint) self.pending_orders = {} self.cached_tickers = {}