예제 #1
0
 def __init__(self, name="anonymous", allocation=None, options={}):
     super().__init__(name=name, allocation=allocation, initialize=False)
     self.Options = options
     self.Portfolio = Portfolio(algorithm=self)
     self.Schedule = ScheduleWrapperManager(self)
     self.Email = Email()
     self.TotalOrders = 0
     self.Initialize()
예제 #2
0
    def test_securities(self):
        brokerage_portfolio = Portfolio(cash=Cash('USD', 200.0, 1.0))
        brokerage_portfolio.CashBook['USD'] = Cash('USD', 200.0, 1.0)
        brokerage_portfolio[BAR] = Position(BAR, 3, 50)

        SetupSingleton(brokerage_portfolio=brokerage_portfolio,
                       securities=[(FOO, 1), (BAR, 10), (XYZ, 100)])

        Singleton.Broker.ImportFromBroker()
        self.assert_portfolio(Singleton.QCAlgorithm.Portfolio, 200, {BAR: 3})
        self.assert_portfolio(Singleton.Broker.Portfolio, 200, {BAR: 3})
예제 #3
0
    def setUp(self):
        brokerage_portfolio = Portfolio(cash=Cash('USD', 100.0, 1.0))
        brokerage_portfolio.CashBook['USD'] = Cash('USD', 100.0, 1.0)

        SetupSingleton(brokerage_portfolio=brokerage_portfolio,
                       securities=[(FOO, 1), (BAR, 10), (XYZ, 100)])
        brokerage_portfolio[BAR] = Position(BAR, 3, 50)
        Singleton.Broker.ImportFromBroker()

        self.algorithm1 = Algorithm(name="alg1")
        self.algorithm1.Portfolio.SetCash(200)
        self.algorithm1.Portfolio[FOO] = Position(FOO, 10, 5)
예제 #4
0
    def test_crypto(self):
        brokerage_portfolio = Portfolio(cash=Cash('USD', 200.0, 1.0))
        brokerage_portfolio.CashBook['USD'] = Cash('USD', 200.0, 1.0)
        brokerage_portfolio.CashBook['BTC'] = Cash('BTC', 0.123, 55_000)

        SetupSingleton(brokerage_portfolio=brokerage_portfolio,
                       securities=[(USD, 1), (BTCUSD, 55_000)])

        self.assert_portfolio_cashbook(Singleton.QCAlgorithm.Portfolio, {
            'USD': 200,
            'BTC': 0.123
        })

        Singleton.Broker.ImportFromBroker()
        self.assert_portfolio(Singleton.Broker.Portfolio, 200, {BTCUSD: 0.123})
예제 #5
0
class TestPortfolioWithMultiplePositions(unittest.TestCase):
    def setUp(self):
        SetupSingleton(securities=[(FOO, 2.5), (BAR, 50)],
                       default_order_status=OrderStatus.Filled)
        self.portfolio = Portfolio(cash=Cash('USD', 270, 1.0))
        self.portfolio[FOO] = Position(FOO, 12, 2.5)  # 30
        self.portfolio[BAR] = Position(BAR, 2, 50)  # 100

    def test_total_value(self):
        self.assertEqual(self.portfolio.TotalPortfolioValue, 400)

    def test_buy_new_position(self):
        abc = Symbol('abc')
        self.portfolio._fill_order(abc, 10.0, 20.0)
        self.assertEqual(len(self.portfolio), 3)
        self.assertEqual(self.portfolio[abc].Quantity, 10)
        self.assertEqual(self.portfolio.Cash, 70)

    def test_buy_existing_position_with_different_price(self):
        self.portfolio._fill_order(BAR, 1.0, 200.0)
        self.assertEqual(len(self.portfolio), 2)
        self.assertEqual(self.portfolio.Cash, 70)
        self.assertEqual(self.portfolio[BAR].Quantity, 3)
        self.assertEqual(self.portfolio[BAR].AveragePrice, 100)

    def test_sell_existing_position(self):
        self.portfolio._fill_order(FOO, -5.0, 4.0)
        self.assertEqual(len(self.portfolio), 2)
        self.assertEqual(self.portfolio.Cash, 290)
        self.assertEqual(self.portfolio[FOO].Quantity, 7)

    def test_sell_existing_position_with_different_price(self):
        self.portfolio._fill_order(BAR, -1.0, 100.0)
        self.assertEqual(len(self.portfolio), 2)
        self.assertEqual(self.portfolio.Cash, 370)
        self.assertEqual(self.portfolio[BAR].Quantity, 1)
        self.assertEqual(self.portfolio[BAR].AveragePrice, 50)

    def test_sell_entire_position(self):
        self.portfolio._fill_order(FOO, -12.0, 4.0)
        self.assertEqual(len(self.portfolio), 2)
        self.assertEqual(self.portfolio.Cash, 318)
예제 #6
0
class TestPortfolioWithSinglePosition(unittest.TestCase):
    def setUp(self):
        SetupSingleton(securities=[(FOO, 2.5), (BAR, 10)],
                       default_order_status=OrderStatus.Filled)
        self.portfolio = Portfolio(cash=Cash('USD', 270, 1.0))
        self.portfolio[FOO] = Position(FOO, 12, 2.5)

    def test_total_value(self):
        self.assertEqual(self.portfolio.TotalPortfolioValue, 300)
        Singleton.QCAlgorithm.Securities['foo'] = Security(FOO, price=3)
        self.assertEqual(self.portfolio.TotalPortfolioValue, 306)

    def test_buy_existing_position(self):
        self.portfolio._fill_order(FOO, 1.0, 9.0)
        self.assertEqual(self.portfolio['foo'].Quantity, 13)
        self.assertEqual(self.portfolio['foo'].AveragePrice, 3)
        self.assertEqual(self.portfolio.Cash, 261)

    def test_sell_existing_position(self):
        self.portfolio._fill_order(FOO, -1.0, 3.0)
        self.assertEqual(self.portfolio[FOO].Quantity, 11)
        self.assertEqual(self.portfolio[FOO].AveragePrice, 2.5)
        self.assertEqual(self.portfolio.Cash, 273)
예제 #7
0
class Algorithm(SimpleAlgorithm):
    def __init__(self, name="anonymous", allocation=None, options={}):
        super().__init__(name=name, allocation=allocation, initialize=False)
        self.Options = options
        self.Portfolio = Portfolio(algorithm=self)
        self.Schedule = ScheduleWrapperManager(self)
        self.Email = Email()
        self.TotalOrders = 0
        self.Initialize()

    def post(self):
        self.Portfolio.ExecuteOrders()

    def __str__(self):
        return "[%s] %s" % (self.Name, str(self.Portfolio))

    def _tag(self, tag):
        return "%s: %s" % (self.Name, tag) if tag else self.Name

    @property
    def Performance(self):
        return round(self.Portfolio.Performance, 2)

    @convert_to_symbol('symbol', Singleton.CreateSymbol)
    def Buy(self, symbol, quantity, tag=""):
        self.Debug("Buy(%s, %f)" % (symbol, quantity))
        return self.Portfolio.createOrder(symbol,
                                          quantity,
                                          OrderType.Market,
                                          tag=self._tag(tag))

    @convert_to_symbol('symbol', Singleton.CreateSymbol)
    def Sell(self, symbol, quantity, tag=""):
        self.Debug("Sell(%s, %f)" % (symbol, quantity))
        return self.Portfolio.createOrder(symbol,
                                          -quantity,
                                          OrderType.Market,
                                          tag=self._tag(tag))

    @convert_to_symbol('symbol', Singleton.CreateSymbol)
    def Order(self, symbol, quantity, tag=""):
        self.Debug("Order(%s, %f) [deprecated]" % (symbol, quantity))
        return self.MarketOrder(symbol, quantity, tag=tag)

    @convert_to_symbol('symbol', Singleton.CreateSymbol)
    def MarketOrder(self, symbol, quantity, tag=""):
        self.Debug("MarketOrder(%s, %f)" % (symbol, quantity))
        return self.Portfolio.createOrder(symbol,
                                          quantity,
                                          OrderType.Market,
                                          tag=self._tag(tag))

    @convert_to_symbol('symbol', Singleton.CreateSymbol)
    def LimitOrder(self, symbol, quantity, limit_price, tag=""):
        self.Debug("LimitOrder(%s, %f)" % (symbol, quantity))
        return self.Portfolio.createOrder(symbol,
                                          quantity,
                                          OrderType.Limit,
                                          limit_price=limit_price,
                                          tag=self._tag(tag))

    @convert_to_symbol('symbol', Singleton.CreateSymbol)
    def StopMarketOrder(self, symbol, quantity, stop_price, tag=""):
        self.Debug("StopMarketOrder(%s, %f)" % (symbol, quantity))
        return self.Portfolio.createOrder(symbol,
                                          quantity,
                                          OrderType.StopMarket,
                                          stop_price=stop_price,
                                          tag=self._tag(tag))

    @convert_to_symbol('symbol', Singleton.CreateSymbol)
    def StopLimitOrder(self,
                       symbol,
                       quantity,
                       stop_price,
                       limit_price,
                       tag=""):
        self.Debug("StopLimitOrder(%s, %f)" % (symbol, quantity))
        return self.Portfolio.createOrder(symbol,
                                          quantity,
                                          OrderType.StopLimit,
                                          stop_price=stop_price,
                                          limit_price=limit_price,
                                          tag=self._tag(tag))

    @convert_to_symbol('symbol', Singleton.CreateSymbol)
    def MarketOnOpenOrder(self, symbol, quantity, tag=""):
        self.Debug("MarketOnOpenOrder(%s, %f)" % (symbol, quantity))
        return self.Portfolio.createOrder(symbol,
                                          quantity,
                                          OrderType.MarketOnOpen,
                                          tag=self._tag(tag))

    @convert_to_symbol('symbol', Singleton.CreateSymbol)
    def MarketOnCloseOrder(self, symbol, quantity, tag=""):
        self.Debug("MarketOnCloseOrder(%s, %f)" % (symbol, quantity))
        return self.Portfolio.createOrder(symbol,
                                          quantity,
                                          OrderType.MarketOnClose,
                                          tag=self._tag(tag))

    @convert_to_symbol('symbol', Singleton.CreateSymbol)
    def OptionExerciseOrder(self, symbol, quantity, tag=""):
        self.Debug("OptionExerciseOrder(%s, %f)" % (symbol, quantity))
        return self.Portfolio.createOrder(symbol,
                                          quantity,
                                          OrderType.OptionExercise,
                                          tag=self._tag(tag))

    @convert_to_symbol('symbol', Singleton.CreateSymbol)
    def Liquidate(self, symbol=None, tag=""):
        self.Debug("Liquidate(%s)" % symbol)
        self.Portfolio.liquidate(symbol=symbol,
                                 tag=self._tag(f"Liquidated {tag}"))
        self.Email.AppendKeyValue(symbol, "0%")

    @convert_to_symbol('symbol', Singleton.CreateSymbol)
    def SetHoldings(self,
                    symbol,
                    percentage,
                    liquidateExistingHoldings=False,
                    tag=""):
        self.Debug("SetHoldings(%s, %f)" % (symbol, percentage))
        if liquidateExistingHoldings:
            to_liquidate = [
                s for s, p in iter(self.Portfolio.items())
                if s != symbol and p.Quantity > 0
            ]
            for s in to_liquidate:
                self.Liquidate(symbol=s, tag=self._tag(tag))

        percentage_str = f"{int(round(100.0*percentage, 0))}%"
        # percentage *= 0.999
        order = self._set_holdings_impl(
            symbol, percentage, tag=self._tag(f"{tag} ({percentage_str})"))
        self.Portfolio.AddOrder(order)
        self.Email.AppendKeyValue(symbol, percentage_str)

    @convert_to_symbol('symbol', Singleton.CreateSymbol)
    def CalculateOrderQuantity(self, symbol, target):
        Singleton.readjust_allocation()
        global_current = Singleton.Portfolio[symbol].Quantity
        local_current = self.Portfolio[symbol].Quantity
        global_order = Singleton.CalculateOrderQuantity(
            symbol, self.Allocation * target)
        global_target = global_order + global_current
        local_order = global_target - local_current

        return local_order

    @accepts(self=object, symbol=Symbol, target=(int, float), tag=str)
    def _set_holdings_impl(self, symbol, target, tag=""):
        qty = self.CalculateOrderQuantity(symbol, target)

        # rounding off Order Quantity to the nearest multiple of Lot Size
        lot_size = Singleton.Securities[symbol].SymbolProperties.LotSize
        if lot_size < 1:
            lot_size = 0.001  # min order on Coinbase Pro
            # lot_size = min(1, 10 * lot_size) # prevent float limitations
            qty -= qty % lot_size

        # Calculate total unfilled quantity for open market orders
        order_ids = self.Broker.GetOrderIdsForPortfolio(self.Portfolio)
        open_orders = [
            Singleton.Transactions.GetOrderById(order_id)
            for order_id in order_ids
        ]
        market_orders_quantity = sum([
            order.Quantity for order in open_orders
            if order.Symbol == symbol and order.Type in (
                OrderType.Market, OrderType.MarketOnOpen)
        ])

        qty -= market_orders_quantity

        return InternalOrder(portfolio=self.Portfolio,
                             symbol=symbol,
                             quantity=qty,
                             tag=tag)

    ######################################################################
    def CreateRollingWindow(self, symbol, window_size):
        rolling_window = RollingWindow[TradeBar](window_size)
        consolidator = TradeBarConsolidator(timedelta(1))
        consolidator.DataConsolidated += lambda _, bar: rolling_window.Add(bar)
        self.SubscriptionManager.AddConsolidator(symbol, consolidator)
        return rolling_window
예제 #8
0
 def setUp(self):
     SetupSingleton(securities=[(FOO, 2.5), (BAR, 50)],
                    default_order_status=OrderStatus.Filled)
     self.portfolio = Portfolio(cash=Cash('USD', 270, 1.0))
     self.portfolio[FOO] = Position(FOO, 12, 2.5)  # 30
     self.portfolio[BAR] = Position(BAR, 2, 50)  # 100
예제 #9
0
    def setUp(self):
        SetupSingleton(
            brokerage_portfolio=Portfolio(cash=Cash('USD', 200.0, 1.0)),
            securities=[(FOO, 1), (BAR, 10), (XYZ, 100)])

        self.portfolio = Portfolio(cash=Cash('USD', 200, 1.0))