pep8 conversion of python algos (#7942)
* pep8 conversion of python algos * adding 10 more pep8 converted algos
This commit is contained in:
@@ -23,35 +23,38 @@ from QuantConnect.Data.Custom.Tiingo import *
|
||||
### <meta name="tag" content="tiingo" />
|
||||
class TiingoPriceAlgorithm(QCAlgorithm):
|
||||
|
||||
def Initialize(self):
|
||||
def initialize(self):
|
||||
# Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
self.SetStartDate(2017, 1, 1)
|
||||
self.SetEndDate(2017, 12, 31)
|
||||
self.SetCash(100000)
|
||||
self.set_start_date(2017, 1, 1)
|
||||
self.set_end_date(2017, 12, 31)
|
||||
self.set_cash(100000)
|
||||
|
||||
# Set your Tiingo API Token here
|
||||
Tiingo.SetAuthCode("my-tiingo-api-token")
|
||||
Tiingo.set_auth_code("my-tiingo-api-token")
|
||||
|
||||
self.ticker = "AAPL"
|
||||
self.symbol = self.AddData(TiingoPrice, self.ticker, Resolution.Daily).Symbol
|
||||
self.equity = self.add_equity(self.ticker).symbol
|
||||
self.aapl = self.add_data(TiingoPrice, self.ticker, Resolution.DAILY).symbol
|
||||
|
||||
self.emaFast = self.EMA(self.symbol, 5)
|
||||
self.emaSlow = self.EMA(self.symbol, 10)
|
||||
self.ema_fast = self.ema(self.equity, 5)
|
||||
self.ema_slow = self.ema(self.equity, 10)
|
||||
|
||||
|
||||
def OnData(self, slice):
|
||||
def on_data(self, slice):
|
||||
# OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
|
||||
if not slice.ContainsKey(self.ticker): return
|
||||
if not slice.contains_key(self.ticker): return
|
||||
|
||||
# Extract Tiingo data from the slice
|
||||
row = slice[self.ticker]
|
||||
|
||||
self.Log(f"{self.Time} - {row.Symbol.Value} - {row.Close} {row.Value} {row.Price} - EmaFast:{self.emaFast} - EmaSlow:{self.emaSlow}")
|
||||
if row is not None:
|
||||
if self.ema_fast.is_ready and self.ema_slow.is_ready:
|
||||
self.log(f"{self.time} - {row.symbol.value} - {row.close} {row.value} {row.price} - EmaFast:{self.ema_fast} - EmaSlow:{self.ema_slow}")
|
||||
|
||||
# Simple EMA cross
|
||||
if not self.Portfolio.Invested and self.emaFast > self.emaSlow:
|
||||
self.SetHoldings(self.symbol, 1)
|
||||
# Simple EMA cross
|
||||
if not self.portfolio.invested and self.ema_fast > self.ema_slow:
|
||||
self.set_holdings(self.equity, 1)
|
||||
|
||||
elif self.Portfolio.Invested and self.emaFast < self.emaSlow:
|
||||
self.Liquidate(self.symbol)
|
||||
elif self.portfolio.invested and self.ema_fast < self.ema_slow:
|
||||
self.liquidate(self.equity)
|
||||
|
||||
@@ -22,81 +22,81 @@ from AlgorithmImports import *
|
||||
class TimeInForceAlgorithm(QCAlgorithm):
|
||||
|
||||
# Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
|
||||
def Initialize(self):
|
||||
def initialize(self):
|
||||
|
||||
self.SetStartDate(2013,10,7)
|
||||
self.SetEndDate(2013,10,11)
|
||||
self.SetCash(100000)
|
||||
self.set_start_date(2013,10,7)
|
||||
self.set_end_date(2013,10,11)
|
||||
self.set_cash(100000)
|
||||
|
||||
# The default time in force setting for all orders is GoodTilCancelled (GTC),
|
||||
# uncomment this line to set a different time in force.
|
||||
# We currently only support GTC and DAY.
|
||||
# self.DefaultOrderProperties.TimeInForce = TimeInForce.Day
|
||||
# self.default_order_properties.time_in_force = TimeInForce.day
|
||||
|
||||
self.symbol = self.AddEquity("SPY", Resolution.Minute).Symbol
|
||||
self.symbol = self.add_equity("SPY", Resolution.MINUTE).symbol
|
||||
|
||||
self.gtcOrderTicket1 = None
|
||||
self.gtcOrderTicket2 = None
|
||||
self.dayOrderTicket1 = None
|
||||
self.dayOrderTicket2 = None
|
||||
self.gtdOrderTicket1 = None
|
||||
self.gtdOrderTicket2 = None
|
||||
self.expectedOrderStatuses = {}
|
||||
self.gtc_order_ticket1 = None
|
||||
self.gtc_order_ticket2 = None
|
||||
self.day_order_ticket1 = None
|
||||
self.day_order_ticket2 = None
|
||||
self.gtd_order_ticket1 = None
|
||||
self.gtd_order_ticket2 = None
|
||||
self.expected_order_statuses = {}
|
||||
|
||||
# OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
# Arguments:
|
||||
# data: Slice object keyed by symbol containing the stock data
|
||||
def OnData(self, data):
|
||||
def on_data(self, data):
|
||||
|
||||
if self.gtcOrderTicket1 is None:
|
||||
if self.gtc_order_ticket1 is None:
|
||||
# These GTC orders will never expire and will not be canceled automatically.
|
||||
|
||||
self.DefaultOrderProperties.TimeInForce = TimeInForce.GoodTilCanceled
|
||||
self.default_order_properties.time_in_force = TimeInForce.GOOD_TIL_CANCELED
|
||||
|
||||
# this order will not be filled before the end of the backtest
|
||||
self.gtcOrderTicket1 = self.LimitOrder(self.symbol, 10, 100)
|
||||
self.expectedOrderStatuses[self.gtcOrderTicket1.OrderId] = OrderStatus.Submitted
|
||||
self.gtc_order_ticket1 = self.limit_order(self.symbol, 10, 100)
|
||||
self.expected_order_statuses[self.gtc_order_ticket1.order_id] = OrderStatus.SUBMITTED
|
||||
|
||||
# this order will be filled before the end of the backtest
|
||||
self.gtcOrderTicket2 = self.LimitOrder(self.symbol, 10, 160)
|
||||
self.expectedOrderStatuses[self.gtcOrderTicket2.OrderId] = OrderStatus.Filled
|
||||
self.gtc_order_ticket2 = self.limit_order(self.symbol, 10, 160)
|
||||
self.expected_order_statuses[self.gtc_order_ticket2.order_id] = OrderStatus.FILLED
|
||||
|
||||
if self.dayOrderTicket1 is None:
|
||||
if self.day_order_ticket1 is None:
|
||||
# These DAY orders will expire at market close,
|
||||
# if not filled by then they will be canceled automatically.
|
||||
|
||||
self.DefaultOrderProperties.TimeInForce = TimeInForce.Day
|
||||
self.default_order_properties.time_in_force = TimeInForce.DAY
|
||||
|
||||
# this order will not be filled before market close and will be canceled
|
||||
self.dayOrderTicket1 = self.LimitOrder(self.symbol, 10, 140)
|
||||
self.expectedOrderStatuses[self.dayOrderTicket1.OrderId] = OrderStatus.Canceled
|
||||
self.day_order_ticket1 = self.limit_order(self.symbol, 10, 140)
|
||||
self.expected_order_statuses[self.day_order_ticket1.order_id] = OrderStatus.CANCELED
|
||||
|
||||
# this order will be filled before market close
|
||||
self.dayOrderTicket2 = self.LimitOrder(self.symbol, 10, 180)
|
||||
self.expectedOrderStatuses[self.dayOrderTicket2.OrderId] = OrderStatus.Filled
|
||||
self.day_order_ticket2 = self.limit_order(self.symbol, 10, 180)
|
||||
self.expected_order_statuses[self.day_order_ticket2.order_id] = OrderStatus.FILLED
|
||||
|
||||
if self.gtdOrderTicket1 is None:
|
||||
if self.gtd_order_ticket1 is None:
|
||||
# These GTD orders will expire on October 10th at market close,
|
||||
# if not filled by then they will be canceled automatically.
|
||||
|
||||
self.DefaultOrderProperties.TimeInForce = TimeInForce.GoodTilDate(datetime(2013, 10, 10))
|
||||
self.default_order_properties.time_in_force = TimeInForce.good_til_date(datetime(2013, 10, 10))
|
||||
|
||||
# this order will not be filled before expiry and will be canceled
|
||||
self.gtdOrderTicket1 = self.LimitOrder(self.symbol, 10, 100)
|
||||
self.expectedOrderStatuses[self.gtdOrderTicket1.OrderId] = OrderStatus.Canceled
|
||||
self.gtd_order_ticket1 = self.limit_order(self.symbol, 10, 100)
|
||||
self.expected_order_statuses[self.gtd_order_ticket1.order_id] = OrderStatus.CANCELED
|
||||
|
||||
# this order will be filled before expiry
|
||||
self.gtdOrderTicket2 = self.LimitOrder(self.symbol, 10, 160)
|
||||
self.expectedOrderStatuses[self.gtdOrderTicket2.OrderId] = OrderStatus.Filled
|
||||
self.gtd_order_ticket2 = self.limit_order(self.symbol, 10, 160)
|
||||
self.expected_order_statuses[self.gtd_order_ticket2.order_id] = OrderStatus.FILLED
|
||||
|
||||
# Order event handler. This handler will be called for all order events, including submissions, fills, cancellations.
|
||||
# This method can be called asynchronously, ensure you use proper locks on thread-unsafe objects
|
||||
def OnOrderEvent(self, orderEvent):
|
||||
self.Debug(f"{self.Time} {orderEvent}")
|
||||
def on_order_event(self, orderEvent):
|
||||
self.debug(f"{self.time} {orderEvent}")
|
||||
|
||||
# End of algorithm run event handler. This method is called at the end of a backtest or live trading operation.
|
||||
def OnEndOfAlgorithm(self):
|
||||
for orderId, expectedStatus in self.expectedOrderStatuses.items():
|
||||
order = self.Transactions.GetOrderById(orderId)
|
||||
if order.Status != expectedStatus:
|
||||
raise Exception(f"Invalid status for order {orderId} - Expected: {expectedStatus}, actual: {order.Status}")
|
||||
def on_end_of_algorithm(self):
|
||||
for orderId, expectedStatus in self.expected_order_statuses.items():
|
||||
order = self.transactions.get_order_by_id(orderId)
|
||||
if order.status != expectedStatus:
|
||||
raise Exception(f"Invalid status for order {orderId} - Expected: {expectedStatus}, actual: {order.status}")
|
||||
|
||||
@@ -22,64 +22,64 @@ from AlgorithmImports import *
|
||||
class TrailingStopOrderRegressionAlgorithm(QCAlgorithm):
|
||||
'''Basic algorithm demonstrating how to place trailing stop orders.'''
|
||||
|
||||
BuyTrailingAmount = 2
|
||||
SellTrailingAmount = 0.5
|
||||
buy_trailing_amount = 2
|
||||
sell_trailing_amount = 0.5
|
||||
|
||||
def Initialize(self):
|
||||
def initialize(self):
|
||||
|
||||
self.SetStartDate(2013,10, 7)
|
||||
self.SetEndDate(2013,10,11)
|
||||
self.SetCash(100000)
|
||||
self.set_start_date(2013,10, 7)
|
||||
self.set_end_date(2013,10,11)
|
||||
self.set_cash(100000)
|
||||
|
||||
self._symbol = self.AddEquity("SPY").Symbol
|
||||
self._symbol = self.add_equity("SPY").symbol
|
||||
|
||||
self._buyOrderTicket: OrderTicket = None
|
||||
self._sellOrderTicket: OrderTicket = None
|
||||
self._previousSlice: Slice = None
|
||||
self._buy_order_ticket: OrderTicket = None
|
||||
self._sell_order_ticket: OrderTicket = None
|
||||
self._previous_slice: Slice = None
|
||||
|
||||
def OnData(self, slice: Slice):
|
||||
if not slice.ContainsKey(self._symbol):
|
||||
def on_data(self, slice: Slice):
|
||||
if not slice.contains_key(self._symbol):
|
||||
return
|
||||
|
||||
if self._buyOrderTicket is None:
|
||||
self._buyOrderTicket = self.TrailingStopOrder(self._symbol, 100, trailingAmount=self.BuyTrailingAmount, trailingAsPercentage=False)
|
||||
elif self._buyOrderTicket.Status != OrderStatus.Filled:
|
||||
stopPrice = self._buyOrderTicket.Get(OrderField.StopPrice)
|
||||
if self._buy_order_ticket is None:
|
||||
self._buy_order_ticket = self.trailing_stop_order(self._symbol, 100, trailing_amount=self.buy_trailing_amount, trailing_as_percentage=False)
|
||||
elif self._buy_order_ticket.status != OrderStatus.FILLED:
|
||||
stop_price = self._buy_order_ticket.get(OrderField.STOP_PRICE)
|
||||
|
||||
# Get the previous bar to compare to the stop price,
|
||||
# because stop price update attempt with the current slice data happens after OnData.
|
||||
low = self._previousSlice.QuoteBars[self._symbol].Ask.Low if self._previousSlice.QuoteBars.ContainsKey(self._symbol) \
|
||||
else self._previousSlice.Bars[self._symbol].Low
|
||||
low = self._previous_slice.quote_bars[self._symbol].ask.low if self._previous_slice.quote_bars.contains_key(self._symbol) \
|
||||
else self._previous_slice.bars[self._symbol].low
|
||||
|
||||
stopPriceToMarketPriceDistance = stopPrice - low
|
||||
if stopPriceToMarketPriceDistance > self.BuyTrailingAmount:
|
||||
raise Exception(f"StopPrice {stopPrice} should be within {self.BuyTrailingAmount} of the previous low price {low} at all times.")
|
||||
stop_price_to_market_price_distance = stop_price - low
|
||||
if stop_price_to_market_price_distance > self.buy_trailing_amount:
|
||||
raise Exception(f"StopPrice {stop_price} should be within {self.buy_trailing_amount} of the previous low price {low} at all times.")
|
||||
|
||||
if self._sellOrderTicket is None:
|
||||
if self.Portfolio.Invested:
|
||||
self._sellOrderTicket = self.TrailingStopOrder(self._symbol, -100, trailingAmount=self.SellTrailingAmount, trailingAsPercentage=False)
|
||||
elif self._sellOrderTicket.Status != OrderStatus.Filled:
|
||||
stopPrice = self._sellOrderTicket.Get(OrderField.StopPrice)
|
||||
if self._sell_order_ticket is None:
|
||||
if self.portfolio.invested:
|
||||
self._sell_order_ticket = self.trailing_stop_order(self._symbol, -100, trailing_amount=self.sell_trailing_amount, trailing_as_percentage=False)
|
||||
elif self._sell_order_ticket.status != OrderStatus.FILLED:
|
||||
stop_price = self._sell_order_ticket.get(OrderField.STOP_PRICE)
|
||||
|
||||
# Get the previous bar to compare to the stop price,
|
||||
# because stop price update attempt with the current slice data happens after OnData.
|
||||
high = self._previousSlice.QuoteBars[self._symbol].Bid.High if self._previousSlice.QuoteBars.ContainsKey(self._symbol) \
|
||||
else self._previousSlice.Bars[self._symbol].High
|
||||
stopPriceToMarketPriceDistance = high - stopPrice
|
||||
if stopPriceToMarketPriceDistance > self.SellTrailingAmount:
|
||||
raise Exception(f"StopPrice {stopPrice} should be within {self.SellTrailingAmount} of the previous high price {high} at all times.")
|
||||
high = self._previous_slice.quote_bars[self._symbol].bid.high if self._previous_slice.quote_bars.contains_key(self._symbol) \
|
||||
else self._previous_slice.bars[self._symbol].high
|
||||
stop_price_to_market_price_distance = high - stop_price
|
||||
if stop_price_to_market_price_distance > self.sell_trailing_amount:
|
||||
raise Exception(f"StopPrice {stop_price} should be within {self.sell_trailing_amount} of the previous high price {high} at all times.")
|
||||
|
||||
self._previousSlice = slice
|
||||
self._previous_slice = slice
|
||||
|
||||
def OnOrderEvent(self, orderEvent: OrderEvent):
|
||||
if orderEvent.Status == OrderStatus.Filled:
|
||||
if orderEvent.Direction == OrderDirection.Buy:
|
||||
stopPrice = self._buyOrderTicket.Get(OrderField.StopPrice)
|
||||
if orderEvent.FillPrice < stopPrice:
|
||||
raise Exception(f"Buy trailing stop order should have filled with price greater than or equal to the stop price {stopPrice}. "
|
||||
f"Fill price: {orderEvent.FillPrice}")
|
||||
def on_order_event(self, orderEvent: OrderEvent):
|
||||
if orderEvent.status == OrderStatus.FILLED:
|
||||
if orderEvent.direction == OrderDirection.BUY:
|
||||
stop_price = self._buy_order_ticket.get(OrderField.STOP_PRICE)
|
||||
if orderEvent.fill_price < stop_price:
|
||||
raise Exception(f"Buy trailing stop order should have filled with price greater than or equal to the stop price {stop_price}. "
|
||||
f"Fill price: {orderEvent.fill_price}")
|
||||
else:
|
||||
stopPrice = self._sellOrderTicket.Get(OrderField.StopPrice)
|
||||
if orderEvent.FillPrice > stopPrice:
|
||||
raise Exception(f"Sell trailing stop order should have filled with price less than or equal to the stop price {stopPrice}. "
|
||||
f"Fill price: {orderEvent.FillPrice}")
|
||||
stop_price = self._sell_order_ticket.get(OrderField.STOP_PRICE)
|
||||
if orderEvent.fill_price > stop_price:
|
||||
raise Exception(f"Sell trailing stop order should have filled with price less than or equal to the stop price {stop_price}. "
|
||||
f"Fill price: {orderEvent.fill_price}")
|
||||
|
||||
@@ -15,31 +15,31 @@ from AlgorithmImports import *
|
||||
from time import sleep
|
||||
|
||||
### <summary>
|
||||
### Example algorithm showing how to use QCAlgorithm.Train method
|
||||
### Example algorithm showing how to use QCAlgorithm.train method
|
||||
### </summary>
|
||||
### <meta name="tag" content="using quantconnect" />
|
||||
### <meta name="tag" content="training" />
|
||||
class TrainingExampleAlgorithm(QCAlgorithm):
|
||||
'''Example algorithm showing how to use QCAlgorithm.Train method'''
|
||||
'''Example algorithm showing how to use QCAlgorithm.train method'''
|
||||
|
||||
def Initialize(self):
|
||||
def initialize(self):
|
||||
|
||||
self.SetStartDate(2013, 10, 7)
|
||||
self.SetEndDate(2013, 10, 14)
|
||||
self.set_start_date(2013, 10, 7)
|
||||
self.set_end_date(2013, 10, 14)
|
||||
|
||||
self.AddEquity("SPY", Resolution.Daily)
|
||||
self.add_equity("SPY", Resolution.DAILY)
|
||||
|
||||
# Set TrainingMethod to be executed immediately
|
||||
self.Train(self.TrainingMethod)
|
||||
self.train(self.training_method)
|
||||
|
||||
# Set TrainingMethod to be executed at 8:00 am every Sunday
|
||||
self.Train(self.DateRules.Every(DayOfWeek.Sunday), self.TimeRules.At(8 , 0), self.TrainingMethod)
|
||||
self.train(self.date_rules.every(DayOfWeek.SUNDAY), self.time_rules.at(8 , 0), self.training_method)
|
||||
|
||||
def TrainingMethod(self):
|
||||
def training_method(self):
|
||||
|
||||
self.Log(f'Start training at {self.Time}')
|
||||
self.log(f'Start training at {self.time}')
|
||||
# Use the historical data to train the machine learning model
|
||||
history = self.History(["SPY"], 200, Resolution.Daily)
|
||||
history = self.history(["SPY"], 200, Resolution.DAILY)
|
||||
|
||||
# ML code:
|
||||
pass
|
||||
|
||||
@@ -21,25 +21,25 @@ from time import sleep
|
||||
### test sets to 0.5 minutes.
|
||||
### </summary>
|
||||
class TrainingInitializeRegressionAlgorithm(QCAlgorithm):
|
||||
'''Example algorithm showing how to use QCAlgorithm.Train method'''
|
||||
'''Example algorithm showing how to use QCAlgorithm.train method'''
|
||||
|
||||
def Initialize(self):
|
||||
def initialize(self):
|
||||
|
||||
self.SetStartDate(2013, 10, 7)
|
||||
self.SetEndDate(2013, 10, 11)
|
||||
self.set_start_date(2013, 10, 7)
|
||||
self.set_end_date(2013, 10, 11)
|
||||
|
||||
self.AddEquity("SPY", Resolution.Daily)
|
||||
self.add_equity("SPY", Resolution.DAILY)
|
||||
|
||||
# this should cause the algorithm to fail
|
||||
# the regression test sets the time limit to 30 seconds and there's one extra
|
||||
# minute in the bucket, so a two minute sleep should result in RuntimeError
|
||||
self.Train(lambda: sleep(150))
|
||||
self.train(lambda: sleep(150))
|
||||
|
||||
# DateRules.Tomorrow combined with TimeRules.Midnight enforces that this event schedule will
|
||||
# DateRules.tomorrow combined with TimeRules.midnight enforces that this event schedule will
|
||||
# have exactly one time, which will fire between the first data point and the next day at
|
||||
# midnight. So after the first data point, it will run this event and sleep long enough to
|
||||
# exceed the static max algorithm time loop time and begin to consume from the leaky bucket
|
||||
# the regression test sets the "algorithm-manager-time-loop-maximum" value to 30 seconds
|
||||
self.Train(self.DateRules.Tomorrow, self.TimeRules.Midnight, lambda: sleep(60))
|
||||
self.train(self.date_rules.tomorrow, self.time_rules.midnight, lambda: sleep(60))
|
||||
# this will consume the single 'minute' available in the leaky bucket
|
||||
# and the regression test will confirm that the leaky bucket is empty
|
||||
|
||||
@@ -17,46 +17,46 @@ from AlgorithmImports import *
|
||||
### Regression algorithm which tests that a two leg currency conversion happens correctly
|
||||
### </summary>
|
||||
class TwoLegCurrencyConversionRegressionAlgorithm(QCAlgorithm):
|
||||
def Initialize(self):
|
||||
self.SetStartDate(2018, 4, 4)
|
||||
self.SetEndDate(2018, 4, 4)
|
||||
self.SetBrokerageModel(BrokerageName.GDAX, AccountType.Cash)
|
||||
def initialize(self):
|
||||
self.set_start_date(2018, 4, 4)
|
||||
self.set_end_date(2018, 4, 4)
|
||||
self.set_brokerage_model(BrokerageName.GDAX, AccountType.CASH)
|
||||
# GDAX doesn't have LTCETH or ETHLTC, but they do have ETHUSD and LTCUSD to form a path between ETH and LTC
|
||||
self.SetAccountCurrency("ETH")
|
||||
self.SetCash("ETH", 100000)
|
||||
self.SetCash("LTC", 100000)
|
||||
self.SetCash("USD", 100000)
|
||||
self.set_account_currency("ETH")
|
||||
self.set_cash("ETH", 100000)
|
||||
self.set_cash("LTC", 100000)
|
||||
self.set_cash("USD", 100000)
|
||||
|
||||
self._ethUsdSymbol = self.AddCrypto("ETHUSD", Resolution.Minute).Symbol
|
||||
self._ltcUsdSymbol = self.AddCrypto("LTCUSD", Resolution.Minute).Symbol
|
||||
self._eth_usd_symbol = self.add_crypto("ETHUSD", Resolution.MINUTE).symbol
|
||||
self._ltc_usd_symbol = self.add_crypto("LTCUSD", Resolution.MINUTE).symbol
|
||||
|
||||
def OnData(self, data):
|
||||
if not self.Portfolio.Invested:
|
||||
self.MarketOrder(self._ltcUsdSymbol, 1)
|
||||
def on_data(self, data):
|
||||
if not self.portfolio.invested:
|
||||
self.market_order(self._ltc_usd_symbol, 1)
|
||||
|
||||
def OnEndOfAlgorithm(self):
|
||||
ltcCash = self.Portfolio.CashBook["LTC"]
|
||||
def on_end_of_algorithm(self):
|
||||
ltc_cash = self.portfolio.cash_book["LTC"]
|
||||
|
||||
conversionSymbols = [x.Symbol for x in ltcCash.CurrencyConversion.ConversionRateSecurities]
|
||||
conversion_symbols = [x.symbol for x in ltc_cash.currency_conversion.conversion_rate_securities]
|
||||
|
||||
if len(conversionSymbols) != 2:
|
||||
if len(conversion_symbols) != 2:
|
||||
raise ValueError(
|
||||
f"Expected two conversion rate securities for LTC to ETH, is {len(conversionSymbols)}")
|
||||
f"Expected two conversion rate securities for LTC to ETH, is {len(conversion_symbols)}")
|
||||
|
||||
if conversionSymbols[0] != self._ltcUsdSymbol:
|
||||
if conversion_symbols[0] != self._ltc_usd_symbol:
|
||||
raise ValueError(
|
||||
f"Expected first conversion rate security from LTC to ETH to be {self._ltcUsdSymbol}, is {conversionSymbols[0]}")
|
||||
f"Expected first conversion rate security from LTC to ETH to be {self._ltc_usd_symbol}, is {conversion_symbols[0]}")
|
||||
|
||||
if conversionSymbols[1] != self._ethUsdSymbol:
|
||||
if conversion_symbols[1] != self._eth_usd_symbol:
|
||||
raise ValueError(
|
||||
f"Expected second conversion rate security from LTC to ETH to be {self._ethUsdSymbol}, is {conversionSymbols[1]}")
|
||||
f"Expected second conversion rate security from LTC to ETH to be {self._eth_usd_symbol}, is {conversion_symbols[1]}")
|
||||
|
||||
ltcUsdValue = self.Securities[self._ltcUsdSymbol].GetLastData().Value
|
||||
ethUsdValue = self.Securities[self._ethUsdSymbol].GetLastData().Value
|
||||
ltc_usd_value = self.securities[self._ltc_usd_symbol].get_last_data().value
|
||||
eth_usd_value = self.securities[self._eth_usd_symbol].get_last_data().value
|
||||
|
||||
expectedConversionRate = ltcUsdValue / ethUsdValue
|
||||
actualConversionRate = ltcCash.ConversionRate
|
||||
expected_conversion_rate = ltc_usd_value / eth_usd_value
|
||||
actual_conversion_rate = ltc_cash.conversion_rate
|
||||
|
||||
if actualConversionRate != expectedConversionRate:
|
||||
if actual_conversion_rate != expected_conversion_rate:
|
||||
raise ValueError(
|
||||
f"Expected conversion rate from LTC to ETH to be {expectedConversionRate}, is {actualConversionRate}")
|
||||
f"Expected conversion rate from LTC to ETH to be {expected_conversion_rate}, is {actual_conversion_rate}")
|
||||
|
||||
@@ -19,22 +19,22 @@ from AlgorithmImports import *
|
||||
### </summary>
|
||||
class UniverseOnlyRegressionAlgorithm(QCAlgorithm):
|
||||
|
||||
def Initialize(self):
|
||||
self.SetStartDate(2020, 12, 1)
|
||||
self.SetEndDate(2020, 12, 12)
|
||||
self.SetCash(100000)
|
||||
def initialize(self):
|
||||
self.set_start_date(2020, 12, 1)
|
||||
self.set_end_date(2020, 12, 12)
|
||||
self.set_cash(100000)
|
||||
|
||||
self.UniverseSettings.Resolution = Resolution.Daily
|
||||
self.universe_settings.resolution = Resolution.DAILY
|
||||
|
||||
# Add universe without a security added
|
||||
self.AddUniverse(self.Universe.ETF("GDVD", self.UniverseSettings, self.FilterUniverse))
|
||||
self.add_universe(self.universe.etf("GDVD", self.universe_settings, self.filter_universe))
|
||||
|
||||
self.selection_done = False
|
||||
|
||||
def FilterUniverse(self, constituents: List[ETFConstituentData]) -> List[Symbol]:
|
||||
def filter_universe(self, constituents: List[ETFConstituentData]) -> List[Symbol]:
|
||||
self.selection_done = True
|
||||
return [x.Symbol for x in constituents]
|
||||
return [x.symbol for x in constituents]
|
||||
|
||||
def OnEndOfAlgorithm(self):
|
||||
def on_end_of_algorithm(self):
|
||||
if not self.selection_done:
|
||||
raise Exception("Universe selection was not performed")
|
||||
|
||||
@@ -14,36 +14,36 @@
|
||||
from AlgorithmImports import *
|
||||
|
||||
### <summary>
|
||||
### Regression algorithm asserting the behavior of Universe.Selected collection
|
||||
### Regression algorithm asserting the behavior of Universe.SELECTED collection
|
||||
### </summary>
|
||||
class UniverseSelectedRegressionAlgorithm(QCAlgorithm):
|
||||
|
||||
def Initialize(self):
|
||||
self.SetStartDate(2014, 3, 25)
|
||||
self.SetEndDate(2014, 3, 27)
|
||||
def initialize(self):
|
||||
self.set_start_date(2014, 3, 25)
|
||||
self.set_end_date(2014, 3, 27)
|
||||
|
||||
self.UniverseSettings.Resolution = Resolution.Daily
|
||||
self.universe_settings.resolution = Resolution.DAILY
|
||||
|
||||
self._universe = self.AddUniverse(self.SelectionFunction)
|
||||
self.selectionCount = 0
|
||||
self._universe = self.add_universe(self.selection_function)
|
||||
self.selection_count = 0
|
||||
|
||||
def SelectionFunction(self, fundamentals):
|
||||
sortedByDollarVolume = sorted(fundamentals, key=lambda x: x.DollarVolume, reverse=True)
|
||||
def selection_function(self, fundamentals):
|
||||
sorted_by_dollar_volume = sorted(fundamentals, key=lambda x: x.dollar_volume, reverse=True)
|
||||
|
||||
sortedByDollarVolume = sortedByDollarVolume[self.selectionCount:]
|
||||
self.selectionCount = self.selectionCount + 1
|
||||
sorted_by_dollar_volume = sorted_by_dollar_volume[self.selection_count:]
|
||||
self.selection_count = self.selection_count + 1
|
||||
|
||||
# return the symbol objects of the top entries from our sorted collection
|
||||
return [ x.Symbol for x in sortedByDollarVolume[:self.selectionCount] ]
|
||||
return [ x.symbol for x in sorted_by_dollar_volume[:self.selection_count] ]
|
||||
|
||||
def OnData(self, data):
|
||||
if Symbol.Create("TSLA", SecurityType.Equity, Market.USA) in self._universe.Selected:
|
||||
def on_data(self, data):
|
||||
if Symbol.create("TSLA", SecurityType.EQUITY, Market.USA) in self._universe.selected:
|
||||
raise ValueError(f"TSLA shouldn't of been selected")
|
||||
|
||||
self.Buy(next(iter(self._universe.Selected)), 1)
|
||||
self.buy(next(iter(self._universe.selected)), 1)
|
||||
|
||||
def OnEndOfAlgorithm(self):
|
||||
if self.selectionCount != 3:
|
||||
raise ValueError(f"Unexpected selection count {self.selectionCount}")
|
||||
if self._universe.Selected.Count != 3 or self._universe.Selected.Count == self._universe.Members.Count:
|
||||
raise ValueError(f"Unexpected universe selected count {self._universe.Selected.Count}")
|
||||
def on_end_of_algorithm(self):
|
||||
if self.selection_count != 3:
|
||||
raise ValueError(f"Unexpected selection count {self.selection_count}")
|
||||
if self._universe.selected.count != 3 or self._universe.selected.count == self._universe.members.count:
|
||||
raise ValueError(f"Unexpected universe selected count {self._universe.selected.count}")
|
||||
|
||||
@@ -21,40 +21,40 @@ from AlgorithmImports import *
|
||||
### <meta name="tag" content="coarse universes" />
|
||||
class UniverseSelectionDefinitionsAlgorithm(QCAlgorithm):
|
||||
|
||||
def Initialize(self):
|
||||
def initialize(self):
|
||||
# subscriptions added via universe selection will have this resolution
|
||||
self.UniverseSettings.Resolution = Resolution.Daily
|
||||
self.universe_settings.resolution = Resolution.DAILY
|
||||
|
||||
self.SetStartDate(2014,3,24) # Set Start Date
|
||||
self.SetEndDate(2014,3,28) # Set End Date
|
||||
self.SetCash(100000) # Set Strategy Cash
|
||||
self.set_start_date(2014,3,24) # Set Start Date
|
||||
self.set_end_date(2014,3,28) # Set End Date
|
||||
self.set_cash(100000) # Set Strategy Cash
|
||||
|
||||
# add universe for the top 3 stocks by dollar volume
|
||||
self.AddUniverse(self.Universe.Top(3))
|
||||
self.add_universe(self.universe.top(3))
|
||||
|
||||
self.changes = None
|
||||
self.onSecuritiesChangedWasCalled = False
|
||||
self.on_securities_changed_was_called = False
|
||||
|
||||
def OnData(self, data):
|
||||
def on_data(self, data):
|
||||
if self.changes is None: return
|
||||
|
||||
# liquidate securities that fell out of our universe
|
||||
for security in self.changes.RemovedSecurities:
|
||||
if security.Invested:
|
||||
self.Liquidate(security.Symbol)
|
||||
for security in self.changes.removed_securities:
|
||||
if security.invested:
|
||||
self.liquidate(security.symbol)
|
||||
|
||||
# invest in securities just added to our universe
|
||||
for security in self.changes.AddedSecurities:
|
||||
if not security.Invested:
|
||||
self.MarketOrder(security.Symbol, 10)
|
||||
for security in self.changes.added_securities:
|
||||
if not security.invested:
|
||||
self.market_order(security.symbol, 10)
|
||||
|
||||
self.changes = None
|
||||
|
||||
# this event fires whenever we have changes to our universe
|
||||
def OnSecuritiesChanged(self, changes):
|
||||
def on_securities_changed(self, changes):
|
||||
self.changes = changes
|
||||
self.onSecuritiesChangedWasCalled = True
|
||||
self.on_securities_changed_was_called = True
|
||||
|
||||
def OnEndOfAlgorithm(self):
|
||||
if not self.onSecuritiesChangedWasCalled:
|
||||
def on_end_of_algorithm(self):
|
||||
if not self.on_securities_changed_was_called:
|
||||
raise Exception("OnSecuritiesChanged() method was never called!")
|
||||
|
||||
@@ -19,60 +19,60 @@ from AlgorithmImports import *
|
||||
### <meta name="tag" content="regression test" />
|
||||
class UniverseSelectionRegressionAlgorithm(QCAlgorithm):
|
||||
|
||||
def Initialize(self):
|
||||
def initialize(self):
|
||||
|
||||
self.SetStartDate(2014,3,22) #Set Start Date
|
||||
self.SetEndDate(2014,4,7) #Set End Date
|
||||
self.SetCash(100000) #Set Strategy Cash
|
||||
self.set_start_date(2014,3,22) #Set Start Date
|
||||
self.set_end_date(2014,4,7) #Set End Date
|
||||
self.set_cash(100000) #Set Strategy Cash
|
||||
# Find more symbols here: http://quantconnect.com/data
|
||||
# security that exists with no mappings
|
||||
self.AddEquity("SPY", Resolution.Daily)
|
||||
self.add_equity("SPY", Resolution.DAILY)
|
||||
# security that doesn't exist until half way in backtest (comes in as GOOCV)
|
||||
self.AddEquity("GOOG", Resolution.Daily)
|
||||
self.add_equity("GOOG", Resolution.DAILY)
|
||||
|
||||
self.UniverseSettings.Resolution = Resolution.Daily
|
||||
self.AddUniverse(self.CoarseSelectionFunction)
|
||||
self.universe_settings.resolution = Resolution.DAILY
|
||||
self.add_universe(self.coarse_selection_function)
|
||||
|
||||
self.delistedSymbols = []
|
||||
self.delisted_symbols = []
|
||||
self.changes = None
|
||||
|
||||
|
||||
def CoarseSelectionFunction(self, coarse):
|
||||
return [ c.Symbol for c in coarse if c.Symbol.Value == "GOOG" or c.Symbol.Value == "GOOCV" or c.Symbol.Value == "GOOAV" or c.Symbol.Value == "GOOGL" ]
|
||||
def coarse_selection_function(self, coarse):
|
||||
return [ c.symbol for c in coarse if c.symbol.value == "GOOG" or c.symbol.value == "GOOCV" or c.symbol.value == "GOOAV" or c.symbol.value == "GOOGL" ]
|
||||
|
||||
|
||||
def OnData(self, data):
|
||||
if self.Transactions.OrdersCount == 0:
|
||||
self.MarketOrder("SPY", 100)
|
||||
def on_data(self, data):
|
||||
if self.transactions.orders_count == 0:
|
||||
self.market_order("SPY", 100)
|
||||
|
||||
for kvp in data.Delistings:
|
||||
self.delistedSymbols.append(kvp.Key)
|
||||
for kvp in data.delistings:
|
||||
self.delisted_symbols.append(kvp.key)
|
||||
|
||||
if self.changes is None:
|
||||
return
|
||||
|
||||
if not all(data.Bars.ContainsKey(x.Symbol) for x in self.changes.AddedSecurities):
|
||||
if not all(data.bars.contains_key(x.symbol) for x in self.changes.added_securities):
|
||||
return
|
||||
|
||||
for security in self.changes.AddedSecurities:
|
||||
self.Log("{0}: Added Security: {1}".format(self.Time, security.Symbol))
|
||||
self.MarketOnOpenOrder(security.Symbol, 100)
|
||||
for security in self.changes.added_securities:
|
||||
self.log("{0}: Added Security: {1}".format(self.time, security.symbol))
|
||||
self.market_on_open_order(security.symbol, 100)
|
||||
|
||||
for security in self.changes.RemovedSecurities:
|
||||
self.Log("{0}: Removed Security: {1}".format(self.Time, security.Symbol))
|
||||
if security.Symbol not in self.delistedSymbols:
|
||||
self.Log("Not in delisted: {0}:".format(security.Symbol))
|
||||
self.MarketOnOpenOrder(security.Symbol, -100)
|
||||
for security in self.changes.removed_securities:
|
||||
self.log("{0}: Removed Security: {1}".format(self.time, security.symbol))
|
||||
if security.symbol not in self.delisted_symbols:
|
||||
self.log("Not in delisted: {0}:".format(security.symbol))
|
||||
self.market_on_open_order(security.symbol, -100)
|
||||
|
||||
self.changes = None
|
||||
|
||||
|
||||
def OnSecuritiesChanged(self, changes):
|
||||
def on_securities_changed(self, changes):
|
||||
self.changes = changes
|
||||
|
||||
|
||||
def OnOrderEvent(self, orderEvent):
|
||||
if orderEvent.Status == OrderStatus.Submitted:
|
||||
self.Log("{0}: Submitted: {1}".format(self.Time, self.Transactions.GetOrderById(orderEvent.OrderId)))
|
||||
if orderEvent.Status == OrderStatus.Filled:
|
||||
self.Log("{0}: Filled: {1}".format(self.Time, self.Transactions.GetOrderById(orderEvent.OrderId)))
|
||||
def on_order_event(self, orderEvent):
|
||||
if orderEvent.status == OrderStatus.SUBMITTED:
|
||||
self.log("{0}: Submitted: {1}".format(self.time, self.transactions.get_order_by_id(orderEvent.order_id)))
|
||||
if orderEvent.status == OrderStatus.FILLED:
|
||||
self.log("{0}: Filled: {1}".format(self.time, self.transactions.get_order_by_id(orderEvent.order_id)))
|
||||
|
||||
@@ -14,49 +14,49 @@
|
||||
from AlgorithmImports import *
|
||||
|
||||
### <summary>
|
||||
### Regression algorithm used to test a fine and coarse selection methods returning Universe.Unchanged
|
||||
### Regression algorithm used to test a fine and coarse selection methods returning Universe.UNCHANGED
|
||||
### </summary>
|
||||
class UniverseUnchangedRegressionAlgorithm(QCAlgorithm):
|
||||
|
||||
def Initialize(self):
|
||||
self.UniverseSettings.Resolution = Resolution.Daily
|
||||
def initialize(self):
|
||||
self.universe_settings.resolution = Resolution.DAILY
|
||||
|
||||
# Order margin value has to have a minimum of 0.5% of Portfolio value, allows filtering out small trades and reduce fees.
|
||||
# Commented so regression algorithm is more sensitive
|
||||
#self.Settings.MinimumOrderMarginPortfolioPercentage = 0.005
|
||||
self.SetStartDate(2014,3,25)
|
||||
self.SetEndDate(2014,4,7)
|
||||
#self.settings.minimum_order_margin_portfolio_percentage = 0.005
|
||||
self.set_start_date(2014,3,25)
|
||||
self.set_end_date(2014,4,7)
|
||||
|
||||
self.SetAlpha(ConstantAlphaModel(InsightType.Price, InsightDirection.Up, timedelta(days = 1), 0.025, None))
|
||||
self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel())
|
||||
self.set_alpha(ConstantAlphaModel(InsightType.PRICE, InsightDirection.UP, timedelta(days = 1), 0.025, None))
|
||||
self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel())
|
||||
|
||||
self.AddUniverse(self.CoarseSelectionFunction, self.FineSelectionFunction)
|
||||
self.add_universe(self.coarse_selection_function, self.fine_selection_function)
|
||||
|
||||
self.numberOfSymbolsFine = 2
|
||||
self.number_of_symbols_fine = 2
|
||||
|
||||
def CoarseSelectionFunction(self, coarse):
|
||||
def coarse_selection_function(self, coarse):
|
||||
# the first and second selection
|
||||
if self.Time.date() <= date(2014, 3, 26):
|
||||
if self.time.date() <= date(2014, 3, 26):
|
||||
tickers = [ "AAPL", "AIG", "IBM" ]
|
||||
return [ Symbol.Create(x, SecurityType.Equity, Market.USA) for x in tickers ]
|
||||
return [ Symbol.create(x, SecurityType.EQUITY, Market.USA) for x in tickers ]
|
||||
|
||||
# will skip fine selection
|
||||
return Universe.Unchanged
|
||||
return Universe.UNCHANGED
|
||||
|
||||
def FineSelectionFunction(self, fine):
|
||||
if self.Time.date() == date(2014, 3, 25):
|
||||
sortedByPeRatio = sorted(fine, key=lambda x: x.ValuationRatios.PERatio, reverse=True)
|
||||
return [ x.Symbol for x in sortedByPeRatio[:self.numberOfSymbolsFine] ]
|
||||
def fine_selection_function(self, fine):
|
||||
if self.time.date() == date(2014, 3, 25):
|
||||
sorted_by_pe_ratio = sorted(fine, key=lambda x: x.valuation_ratios.pe_ratio, reverse=True)
|
||||
return [ x.symbol for x in sorted_by_pe_ratio[:self.number_of_symbols_fine] ]
|
||||
|
||||
# the second selection will return unchanged, in the following fine selection will be skipped
|
||||
return Universe.Unchanged
|
||||
return Universe.UNCHANGED
|
||||
|
||||
# assert security changes, throw if called more than once
|
||||
def OnSecuritiesChanged(self, changes):
|
||||
addedSymbols = [ x.Symbol for x in changes.AddedSecurities ]
|
||||
if (len(changes.AddedSecurities) != 2
|
||||
or self.Time.date() != date(2014, 3, 25)
|
||||
or Symbol.Create("AAPL", SecurityType.Equity, Market.USA) not in addedSymbols
|
||||
or Symbol.Create("IBM", SecurityType.Equity, Market.USA) not in addedSymbols):
|
||||
def on_securities_changed(self, changes):
|
||||
added_symbols = [ x.symbol for x in changes.added_securities ]
|
||||
if (len(changes.added_securities) != 2
|
||||
or self.time.date() != date(2014, 3, 25)
|
||||
or Symbol.create("AAPL", SecurityType.EQUITY, Market.USA) not in added_symbols
|
||||
or Symbol.create("IBM", SecurityType.EQUITY, Market.USA) not in added_symbols):
|
||||
raise ValueError("Unexpected security changes")
|
||||
self.Log(f"OnSecuritiesChanged({self.Time}):: {changes}")
|
||||
self.log(f"OnSecuritiesChanged({self.time}):: {changes}")
|
||||
|
||||
@@ -17,35 +17,35 @@ from AlgorithmImports import *
|
||||
### Example and regression algorithm asserting the behavior of registering and unregistering an indicator from the engine
|
||||
### </summary>
|
||||
class UnregisterIndicatorRegressionAlgorithm(QCAlgorithm):
|
||||
def Initialize(self):
|
||||
def initialize(self):
|
||||
'''Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.'''
|
||||
self.SetStartDate(2013,10, 7)
|
||||
self.SetEndDate(2013,10,11)
|
||||
self.set_start_date(2013,10, 7)
|
||||
self.set_end_date(2013,10,11)
|
||||
|
||||
spy = self.AddEquity("SPY")
|
||||
ibm = self.AddEquity("IBM")
|
||||
spy = self.add_equity("SPY")
|
||||
ibm = self.add_equity("IBM")
|
||||
|
||||
self._symbols = [ spy.Symbol, ibm.Symbol ]
|
||||
self._trin = self.TRIN(self._symbols, Resolution.Minute)
|
||||
self._symbols = [ spy.symbol, ibm.symbol ]
|
||||
self._trin = self.trin(self._symbols, Resolution.MINUTE)
|
||||
self._trin2 = None
|
||||
|
||||
def OnData(self, data):
|
||||
def on_data(self, data):
|
||||
'''OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
|
||||
|
||||
Arguments:
|
||||
data: Slice object keyed by symbol containing the stock data
|
||||
'''
|
||||
if self._trin.IsReady:
|
||||
self._trin.Reset()
|
||||
self.UnregisterIndicator(self._trin)
|
||||
if self._trin.is_ready:
|
||||
self._trin.reset()
|
||||
self.unregister_indicator(self._trin)
|
||||
|
||||
# let's create a new one with a differente resolution
|
||||
self._trin2 = self.TRIN(self._symbols, Resolution.Hour)
|
||||
self._trin2 = self.trin(self._symbols, Resolution.HOUR)
|
||||
|
||||
if not self._trin2 is None and self._trin2.IsReady:
|
||||
if self._trin.IsReady:
|
||||
if not self._trin2 is None and self._trin2.is_ready:
|
||||
if self._trin.is_ready:
|
||||
raise ValueError("Indicator should of stop getting updates!")
|
||||
|
||||
if not self.Portfolio.Invested:
|
||||
self.SetHoldings(self._symbols[0], 0.5)
|
||||
self.SetHoldings(self._symbols[1], 0.5)
|
||||
if not self.portfolio.invested:
|
||||
self.set_holdings(self._symbols[0], 0.5)
|
||||
self.set_holdings(self._symbols[1], 0.5)
|
||||
|
||||
@@ -20,15 +20,15 @@ from math import copysign
|
||||
### <meta name="tag" content="regression test" />
|
||||
class UpdateOrderRegressionAlgorithm(QCAlgorithm):
|
||||
|
||||
def Initialize(self):
|
||||
def initialize(self):
|
||||
'''Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.'''
|
||||
|
||||
self.SetStartDate(2013,1,1) #Set Start Date
|
||||
self.SetEndDate(2015,1,1) #Set End Date
|
||||
self.SetCash(100000) #Set Strategy Cash
|
||||
self.set_start_date(2013,1,1) #Set Start Date
|
||||
self.set_end_date(2015,1,1) #Set End Date
|
||||
self.set_cash(100000) #Set Strategy Cash
|
||||
# Find more symbols here: http://quantconnect.com/data
|
||||
|
||||
self.security = self.AddEquity("SPY", Resolution.Daily)
|
||||
self.security = self.add_equity("SPY", Resolution.DAILY)
|
||||
|
||||
self.last_month = -1
|
||||
self.quantity = 100
|
||||
@@ -39,86 +39,86 @@ class UpdateOrderRegressionAlgorithm(QCAlgorithm):
|
||||
self.limit_percentage = 0.025
|
||||
self.limit_percentage_delta = 0.005
|
||||
|
||||
OrderTypeEnum = [OrderType.Market, OrderType.Limit, OrderType.StopMarket, OrderType.StopLimit, OrderType.MarketOnOpen, OrderType.MarketOnClose, OrderType.TrailingStop]
|
||||
self.order_types_queue = CircularQueue[OrderType](OrderTypeEnum)
|
||||
self.order_types_queue.CircleCompleted += self.onCircleCompleted
|
||||
order_type_enum = [OrderType.MARKET, OrderType.LIMIT, OrderType.STOP_MARKET, OrderType.STOP_LIMIT, OrderType.MARKET_ON_OPEN, OrderType.MARKET_ON_CLOSE, OrderType.TRAILING_STOP]
|
||||
self.order_types_queue = CircularQueue[OrderType](order_type_enum)
|
||||
self.order_types_queue.circle_completed += self.on_circle_completed
|
||||
self.tickets = []
|
||||
|
||||
|
||||
def onCircleCompleted(self, sender, event):
|
||||
def on_circle_completed(self, sender, event):
|
||||
'''Flip our signs when we've gone through all the order types'''
|
||||
self.quantity *= -1
|
||||
|
||||
|
||||
def OnData(self, data):
|
||||
def on_data(self, data):
|
||||
'''OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.'''
|
||||
if not data.ContainsKey("SPY"):
|
||||
if not data.contains_key("SPY"):
|
||||
return
|
||||
|
||||
if self.Time.month != self.last_month:
|
||||
if self.time.month != self.last_month:
|
||||
# we'll submit the next type of order from the queue
|
||||
orderType = self.order_types_queue.Dequeue()
|
||||
order_type = self.order_types_queue.dequeue()
|
||||
#Log("")
|
||||
self.Log("\r\n--------------MONTH: {0}:: {1}\r\n".format(self.Time.strftime("%B"), orderType))
|
||||
self.Log("\r\n--------------MONTH: {0}:: {1}".format(self.time.strftime("%B"), order_type))
|
||||
#Log("")
|
||||
self.last_month = self.Time.month
|
||||
self.Log("ORDER TYPE:: {0}".format(orderType))
|
||||
isLong = self.quantity > 0
|
||||
stopPrice = (1 + self.stop_percentage)*data["SPY"].High if isLong else (1 - self.stop_percentage)*data["SPY"].Low
|
||||
limitPrice = (1 - self.limit_percentage)*stopPrice if isLong else (1 + self.limit_percentage)*stopPrice
|
||||
self.last_month = self.time.month
|
||||
self.log("ORDER TYPE:: {0}".format(order_type))
|
||||
is_long = self.quantity > 0
|
||||
stop_price = (1 + self.stop_percentage)*data["SPY"].high if is_long else (1 - self.stop_percentage)*data["SPY"].low
|
||||
limit_price = (1 - self.limit_percentage)*stop_price if is_long else (1 + self.limit_percentage)*stop_price
|
||||
|
||||
if orderType == OrderType.Limit:
|
||||
limitPrice = (1 + self.limit_percentage)*data["SPY"].High if not isLong else (1 - self.limit_percentage)*data["SPY"].Low
|
||||
if order_type == OrderType.LIMIT:
|
||||
limit_price = (1 + self.limit_percentage)*data["SPY"].high if not is_long else (1 - self.limit_percentage)*data["SPY"].low
|
||||
|
||||
request = SubmitOrderRequest(orderType, self.security.Symbol.SecurityType, "SPY", self.quantity, stopPrice, limitPrice, 0, 0.01, True,
|
||||
self.UtcTime, str(orderType))
|
||||
ticket = self.Transactions.AddOrder(request)
|
||||
request = SubmitOrderRequest(order_type, self.security.symbol.security_type, "SPY", self.quantity, stop_price, limit_price, 0, 0.01, True,
|
||||
self.utc_time, str(order_type))
|
||||
ticket = self.transactions.add_order(request)
|
||||
self.tickets.append(ticket)
|
||||
|
||||
elif len(self.tickets) > 0:
|
||||
ticket = self.tickets[-1]
|
||||
|
||||
if self.Time.day > 8 and self.Time.day < 14:
|
||||
if len(ticket.UpdateRequests) == 0 and ticket.Status is not OrderStatus.Filled:
|
||||
self.Log("TICKET:: {0}".format(ticket))
|
||||
updateOrderFields = UpdateOrderFields()
|
||||
updateOrderFields.Quantity = ticket.Quantity + copysign(self.delta_quantity, self.quantity)
|
||||
updateOrderFields.Tag = "Change quantity: {0}".format(self.Time.day)
|
||||
ticket.Update(updateOrderFields)
|
||||
if self.time.day > 8 and self.time.day < 14:
|
||||
if len(ticket.update_requests) == 0 and ticket.status is not OrderStatus.FILLED:
|
||||
self.log("TICKET:: {0}".format(ticket))
|
||||
update_order_fields = UpdateOrderFields()
|
||||
update_order_fields.quantity = ticket.quantity + copysign(self.delta_quantity, self.quantity)
|
||||
update_order_fields.tag = "Change quantity: {0}".format(self.time.day)
|
||||
ticket.update(update_order_fields)
|
||||
|
||||
elif self.Time.day > 13 and self.Time.day < 20:
|
||||
if len(ticket.UpdateRequests) == 1 and ticket.Status is not OrderStatus.Filled:
|
||||
self.Log("TICKET:: {0}".format(ticket))
|
||||
updateOrderFields = UpdateOrderFields()
|
||||
updateOrderFields.LimitPrice = self.security.Price*(1 - copysign(self.limit_percentage_delta, ticket.Quantity))
|
||||
updateOrderFields.StopPrice = self.security.Price*(1 + copysign(self.stop_percentage_delta, ticket.Quantity)) if ticket.OrderType != OrderType.TrailingStop else None
|
||||
updateOrderFields.Tag = "Change prices: {0}".format(self.Time.day)
|
||||
ticket.Update(updateOrderFields)
|
||||
elif self.time.day > 13 and self.time.day < 20:
|
||||
if len(ticket.update_requests) == 1 and ticket.status is not OrderStatus.FILLED:
|
||||
self.log("TICKET:: {0}".format(ticket))
|
||||
update_order_fields = UpdateOrderFields()
|
||||
update_order_fields.limit_price = self.security.price*(1 - copysign(self.limit_percentage_delta, ticket.quantity))
|
||||
update_order_fields.stop_price = self.security.price*(1 + copysign(self.stop_percentage_delta, ticket.quantity)) if ticket.order_type != OrderType.TRAILING_STOP else None
|
||||
update_order_fields.tag = "Change prices: {0}".format(self.time.day)
|
||||
ticket.update(update_order_fields)
|
||||
else:
|
||||
if len(ticket.UpdateRequests) == 2 and ticket.Status is not OrderStatus.Filled:
|
||||
self.Log("TICKET:: {0}".format(ticket))
|
||||
ticket.Cancel("{0} and is still open!".format(self.Time.day))
|
||||
self.Log("CANCELLED:: {0}".format(ticket.CancelRequest))
|
||||
if len(ticket.update_requests) == 2 and ticket.status is not OrderStatus.FILLED:
|
||||
self.log("TICKET:: {0}".format(ticket))
|
||||
ticket.cancel("{0} and is still open!".format(self.time.day))
|
||||
self.log("CANCELLED:: {0}".format(ticket.cancel_request))
|
||||
|
||||
|
||||
def OnOrderEvent(self, orderEvent):
|
||||
order = self.Transactions.GetOrderById(orderEvent.OrderId)
|
||||
ticket = self.Transactions.GetOrderTicket(orderEvent.OrderId)
|
||||
def on_order_event(self, orderEvent):
|
||||
order = self.transactions.get_order_by_id(orderEvent.order_id)
|
||||
ticket = self.transactions.get_order_ticket(orderEvent.order_id)
|
||||
|
||||
#order cancelations update CanceledTime
|
||||
if order.Status == OrderStatus.Canceled and order.CanceledTime != orderEvent.UtcTime:
|
||||
if order.status == OrderStatus.CANCELED and order.canceled_time != orderEvent.utc_time:
|
||||
raise ValueError("Expected canceled order CanceledTime to equal canceled order event time.")
|
||||
|
||||
#fills update LastFillTime
|
||||
if (order.Status == OrderStatus.Filled or order.Status == OrderStatus.PartiallyFilled) and order.LastFillTime != orderEvent.UtcTime:
|
||||
if (order.status == OrderStatus.FILLED or order.status == OrderStatus.PARTIALLY_FILLED) and order.last_fill_time != orderEvent.utc_time:
|
||||
raise ValueError("Expected filled order LastFillTime to equal fill order event time.")
|
||||
|
||||
# check the ticket to see if the update was successfully processed
|
||||
if len([ur for ur in ticket.UpdateRequests if ur.Response is not None and ur.Response.IsSuccess]) > 0 and order.CreatedTime != self.UtcTime and order.LastUpdateTime is None:
|
||||
if len([ur for ur in ticket.update_requests if ur.response is not None and ur.response.is_success]) > 0 and order.created_time != self.utc_time and order.last_update_time is None:
|
||||
raise ValueError("Expected updated order LastUpdateTime to equal submitted update order event time")
|
||||
|
||||
if orderEvent.Status == OrderStatus.Filled:
|
||||
self.Log("FILLED:: {0} FILL PRICE:: {1}".format(self.Transactions.GetOrderById(orderEvent.OrderId), orderEvent.FillPrice))
|
||||
if orderEvent.status == OrderStatus.FILLED:
|
||||
self.log("FILLED:: {0} FILL PRICE:: {1}".format(self.transactions.get_order_by_id(orderEvent.order_id), orderEvent.fill_price))
|
||||
else:
|
||||
self.Log(orderEvent.ToString())
|
||||
self.Log("TICKET:: {0}".format(ticket))
|
||||
self.log(orderEvent.to_string())
|
||||
self.log("TICKET:: {0}".format(ticket))
|
||||
|
||||
@@ -26,26 +26,26 @@ from System.Collections.Generic import List
|
||||
### <meta name="tag" content="custom universes" />
|
||||
class UserDefinedUniverseAlgorithm(QCAlgorithm):
|
||||
|
||||
def Initialize(self):
|
||||
self.SetCash(100000)
|
||||
self.SetStartDate(2015,1,1)
|
||||
self.SetEndDate(2015,12,1)
|
||||
def initialize(self):
|
||||
self.set_cash(100000)
|
||||
self.set_start_date(2015,1,1)
|
||||
self.set_end_date(2015,12,1)
|
||||
self.symbols = [ "SPY", "GOOG", "IBM", "AAPL", "MSFT", "CSCO", "ADBE", "WMT"]
|
||||
|
||||
self.UniverseSettings.Resolution = Resolution.Hour
|
||||
self.AddUniverse('my_universe_name', Resolution.Hour, self.selection)
|
||||
self.universe_settings.resolution = Resolution.HOUR
|
||||
self.add_universe('my_universe_name', Resolution.HOUR, self.selection)
|
||||
|
||||
def selection(self, time):
|
||||
index = time.hour%len(self.symbols)
|
||||
return self.symbols[index]
|
||||
return [self.symbols[index]]
|
||||
|
||||
def OnData(self, slice):
|
||||
def on_data(self, slice):
|
||||
pass
|
||||
|
||||
def OnSecuritiesChanged(self, changes):
|
||||
for removed in changes.RemovedSecurities:
|
||||
if removed.Invested:
|
||||
self.Liquidate(removed.Symbol)
|
||||
def on_securities_changed(self, changes):
|
||||
for removed in changes.removed_securities:
|
||||
if removed.invested:
|
||||
self.liquidate(removed.symbol)
|
||||
|
||||
for added in changes.AddedSecurities:
|
||||
self.SetHoldings(added.Symbol, 1/float(len(changes.AddedSecurities)))
|
||||
for added in changes.added_securities:
|
||||
self.set_holdings(added.symbol, 1/float(len(changes.added_securities)))
|
||||
|
||||
@@ -21,53 +21,53 @@ from AlgorithmImports import *
|
||||
### <meta name="tag" content="consolidating data" />
|
||||
class VolumeRenkoConsolidatorAlgorithm(QCAlgorithm):
|
||||
|
||||
def Initialize(self):
|
||||
self.SetStartDate(2013, 10, 7)
|
||||
self.SetEndDate(2013, 10, 11)
|
||||
self.SetCash(100000)
|
||||
def initialize(self):
|
||||
self.set_start_date(2013, 10, 7)
|
||||
self.set_end_date(2013, 10, 11)
|
||||
self.set_cash(100000)
|
||||
|
||||
self.sma = SimpleMovingAverage(10)
|
||||
self.tick_consolidated = False
|
||||
|
||||
self.spy = self.AddEquity("SPY", Resolution.Minute).Symbol
|
||||
self.spy = self.add_equity("SPY", Resolution.MINUTE).symbol
|
||||
self.tradebar_volume_consolidator = VolumeRenkoConsolidator(1000000)
|
||||
self.tradebar_volume_consolidator.DataConsolidated += self.OnSPYDataConsolidated
|
||||
self.tradebar_volume_consolidator.data_consolidated += self.on_spy_data_consolidated
|
||||
|
||||
self.ibm = self.AddEquity("IBM", Resolution.Tick).Symbol
|
||||
self.ibm = self.add_equity("IBM", Resolution.TICK).symbol
|
||||
self.tick_volume_consolidator = VolumeRenkoConsolidator(1000000)
|
||||
self.tick_volume_consolidator.DataConsolidated += self.OnIBMDataConsolidated
|
||||
self.tick_volume_consolidator.data_consolidated += self.on_ibm_data_consolidated
|
||||
|
||||
history = self.History[TradeBar](self.spy, 1000, Resolution.Minute);
|
||||
history = self.history[TradeBar](self.spy, 1000, Resolution.MINUTE)
|
||||
for bar in history:
|
||||
self.tradebar_volume_consolidator.Update(bar)
|
||||
self.tradebar_volume_consolidator.update(bar)
|
||||
|
||||
def OnSPYDataConsolidated(self, sender, bar):
|
||||
self.sma.Update(bar.EndTime, bar.Value)
|
||||
self.Debug(f"SPY {bar.Time} to {bar.EndTime} :: O:{bar.Open} H:{bar.High} L:{bar.Low} C:{bar.Close} V:{bar.Volume}")
|
||||
if bar.Volume != 1000000:
|
||||
def on_spy_data_consolidated(self, sender, bar):
|
||||
self.sma.update(bar.end_time, bar.value)
|
||||
self.debug(f"SPY {bar.time} to {bar.end_time} :: O:{bar.open} H:{bar.high} L:{bar.low} C:{bar.close} V:{bar.volume}")
|
||||
if bar.volume != 1000000:
|
||||
raise Exception("Volume of consolidated bar does not match set value!")
|
||||
|
||||
def OnIBMDataConsolidated(self, sender, bar):
|
||||
self.Debug(f"IBM {bar.Time} to {bar.EndTime} :: O:{bar.Open} H:{bar.High} L:{bar.Low} C:{bar.Close} V:{bar.Volume}")
|
||||
if bar.Volume != 1000000:
|
||||
def on_ibm_data_consolidated(self, sender, bar):
|
||||
self.debug(f"IBM {bar.time} to {bar.end_time} :: O:{bar.open} H:{bar.high} L:{bar.low} C:{bar.close} V:{bar.volume}")
|
||||
if bar.volume != 1000000:
|
||||
raise Exception("Volume of consolidated bar does not match set value!")
|
||||
self.tick_consolidated = True
|
||||
|
||||
def OnData(self, slice):
|
||||
def on_data(self, slice):
|
||||
# Update by TradeBar
|
||||
if slice.Bars.ContainsKey(self.spy):
|
||||
self.tradebar_volume_consolidator.Update(slice.Bars[self.spy])
|
||||
if slice.bars.contains_key(self.spy):
|
||||
self.tradebar_volume_consolidator.update(slice.bars[self.spy])
|
||||
|
||||
# Update by Tick
|
||||
if slice.Ticks.ContainsKey(self.ibm):
|
||||
for tick in slice.Ticks[self.ibm]:
|
||||
self.tick_volume_consolidator.Update(tick)
|
||||
if slice.ticks.contains_key(self.ibm):
|
||||
for tick in slice.ticks[self.ibm]:
|
||||
self.tick_volume_consolidator.update(tick)
|
||||
|
||||
if self.sma.IsReady and self.sma.Current.Value < self.Securities[self.spy].Price:
|
||||
self.SetHoldings(self.spy, 1)
|
||||
if self.sma.is_ready and self.sma.current.value < self.securities[self.spy].price:
|
||||
self.set_holdings(self.spy, 1)
|
||||
else:
|
||||
self.SetHoldings(self.spy, 0)
|
||||
self.set_holdings(self.spy, 0)
|
||||
|
||||
def OnEndOfAlgorithm(self):
|
||||
def on_end_of_algorithm(self):
|
||||
if not self.tick_consolidated:
|
||||
raise Exception("Tick consolidator was never been called")
|
||||
Reference in New Issue
Block a user