# QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. # Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from AlgorithmImports import * ### ### This algorithm shows how to grab symbols from an external api each day ### and load data using the universe selection feature. In this example we ### define a custom data type for the NYSE top gainers and then short the ### top 2 gainers each day ### ### ### ### class CustomDataUniverseAlgorithm(QCAlgorithm): def initialize(self): # Data ADDED via universe selection is added with Daily resolution. self.universe_settings.resolution = Resolution.DAILY self.set_start_date(2015,1,5) self.set_end_date(2015,7,1) self.set_cash(100000) self.add_equity("SPY", Resolution.DAILY) self.set_benchmark("SPY") # add a custom universe data source (defaults to usa-equity) self.add_universe(NyseTopGainers, "universe-nyse-top-gainers", Resolution.DAILY, self.nyse_top_gainers) def nyse_top_gainers(self, data): return [ x.symbol for x in data if x["TopGainersRank"] <= 2 ] def on_data(self, slice): pass def on_securities_changed(self, changes): self._changes = changes for security in changes.removed_securities: # liquidate securities that have been removed if security.invested: self.liquidate(security.symbol) self.log("Exit {0} at {1}".format(security.symbol, security.close)) for security in changes.added_securities: # enter short positions on new securities if not security.invested and security.close != 0: qty = self.calculate_order_quantity(security.symbol, -0.25) self.market_on_open_order(security.symbol, qty) self.log("Enter {0} at {1}".format(security.symbol, security.close)) class NyseTopGainers(PythonData): def __init__(self): self.count = 0 self.last_date = datetime.min def get_source(self, config, date, is_live_mode): url = "http://www.wsj.com/mdc/public/page/2_3021-gainnyse-gainer.html" if is_live_mode else \ "https://www.dropbox.com/s/vrn3p38qberw3df/nyse-gainers.csv?dl=1" return SubscriptionDataSource(url, SubscriptionTransportMedium.REMOTE_FILE) def reader(self, config, line, date, is_live_mode): if not is_live_mode: # backtest gets data from csv file in dropbox if not (line.strip() and line[0].isdigit()): return None csv = line.split(',') nyse = NyseTopGainers() nyse.time = datetime.strptime(csv[0], "%Y%m%d") nyse.end_time = nyse.time + timedelta(1) nyse.symbol = Symbol.create(csv[1], SecurityType.EQUITY, Market.USA) nyse["TopGainersRank"] = int(csv[2]) return nyse if self.last_date != date: # reset our counter for the new day self.last_date = date self.count = 0 # parse the html into a symbol if not line.startswith('