Esempio n. 1
0
    def test_dividends_multiple_assets(self):
        start_date = date(1986, 12, 31)
        end_date = date(2019, 12, 31)

        msft_vals = self.msft_vals.reindex(pd.date_range(start_date, end_date)).ffill()
        msft_dividends = self.msft_dividends.reindex(
            pd.date_range(start_date, end_date)
        ).dropna()
        aapl_vals = self.aapl_vals.reindex(pd.date_range(start_date, end_date)).ffill()
        aapl_dividends = self.aapl_dividends.reindex(
            pd.date_range(start_date, end_date)
        ).dropna()

        assets = [
            anda.Asset("MSFT", Decimal("0.5"), msft_vals, msft_dividends),
            anda.Asset("AAPL", Decimal("0.5"), aapl_vals, aapl_dividends),
        ]

        strategy = anda.Strategy(
            start_date,
            end_date,
            self.starting_balance,
            assets,
            self.contribution_dates,
            self.contribution_amount,
            self.rebalancing_dates,
        )
        self.assertAlmostEqual(
            anda.total_return(strategy)[end_date], Decimal("9856511.60"), delta=1
        )
Esempio n. 2
0
    def test_sortino_ratio_multi_asset(self):
        start_date = date(1989, 12, 29)
        end_date = date(2000, 12, 29)

        msft_vals = self.msft_vals.reindex(pd.date_range(start_date, end_date)).ffill()
        berkshire_vals = self.berkshire_vals.reindex(
            pd.date_range(start_date, end_date)
        ).ffill()
        risk_free_vals = (
            self.risk_free_vals.dropna()["Close"]
            .reindex(pd.date_range(start_date, end_date))
            .ffill()
        )

        assets = [
            anda.Asset("MSFT", Decimal(0.6), msft_vals),
            anda.Asset("BRK-A", Decimal(0.4), berkshire_vals),
        ]

        strategy = anda.Strategy(
            start_date,
            end_date,
            self.starting_balance,
            assets,
            self.contribution_dates,
            self.contribution_amount,
            self.rebalancing_dates,
        )
        self.assertAlmostEqual(
            anda.sortino_ratio(strategy, risk_free_vals), Decimal("1.56"), delta=0.2
        )
Esempio n. 3
0
    def test_mult_assets(self):
        starting_balance = Decimal("100.00")
        contribution_dates = set()
        contribution_amount = Decimal("0.0")
        rebalancing_dates = set()

        assets = [
            anda.Asset("GOLD", Decimal("0.4"), self.gold_data),
            anda.Asset("SLV", Decimal("0.6"), self.silver_data),
        ]

        strategy = anda.Strategy(
            self.start,
            self.end,
            starting_balance,
            assets,
            contribution_dates,
            contribution_amount,
            rebalancing_dates,
        )

        roi = anda.total_return(strategy)
        self.assertEqual(roi[self.start], Decimal("100.00"))
        self.assertEqual(roi[self.start + timedelta(days=14)], Decimal("220.40"))
        self.assertEqual(roi[self.end], Decimal("320.40"))
Esempio n. 4
0
def get_assets(tickers, proportions, start_date, end_date):
    """
    Gets data for each ticker and puts it in an anda.Asset.
    Returns a list of all assets.
    """
    assert len(tickers) == len(proportions)
    data = util.get_data(tickers, start_date, end_date)
    data = data.rename(columns={
        "AOpen": "Open",
        "AClose": "Close",
        "ALow": "Low",
        "AHigh": "High"
    })

    if data.empty:
        # raise error
        return None

    assets = []
    for tick, prop in zip(tickers, proportions):
        asset_data = data[(data.AssetTicker == tick)]
        only_market_data = asset_data[[
            "ADate", "Open", "Close", "Low", "High"
        ]]
        only_market_data.index = only_market_data["ADate"]
        assets.append(anda.Asset(tick, prop, only_market_data))
    return assets
Esempio n. 5
0
    def test_msft(self):
        start_date = date(1986, 3, 13)
        end_date = date(2019, 1, 1)
        msft_vals = self.msft_vals.reindex(pd.date_range(start_date, end_date)).ffill()
        msft_dividends = self.msft_dividends.reindex(
            pd.date_range(start_date, end_date)
        ).dropna()

        assets = [anda.Asset("MSFT", Decimal("1.0"), msft_vals, msft_dividends)]

        strategy = anda.Strategy(
            start_date,
            end_date,
            self.starting_balance,
            assets,
            self.contribution_dates,
            self.contribution_amount,
            self.rebalancing_dates,
        )
        annual_returns = anda.relative_yearly_returns(strategy)
        expected = [
            #   (year, change)
            (1987, Decimal("125")),
            (1988, Decimal("-2")),
            (2000, Decimal("-63")),
            (2001, Decimal("53")),
            (2002, Decimal("-22")),
            (2003, Decimal("7")),
            (2017, Decimal("41")),
            (2018, Decimal("21")),
        ]
        for year, change in expected:
            self.assertAlmostEqual(
                annual_returns.at[date(year, 1, 1)], change, delta=Decimal("0.5")
            )
Esempio n. 6
0
    def test_short_time(self):
        start_date = date(1989, 1, 4)
        end_date = date(1989, 12, 31)

        self.msft_vals = self.msft_vals.reindex(
            pd.date_range(start_date, end_date)
        ).ffill()

        assets = [
            anda.Asset("MSFT", Decimal("1.0"), self.msft_vals),
        ]

        strategy = anda.Strategy(
            start_date,
            end_date,
            self.starting_balance,
            assets,
            self.contribution_dates,
            self.contribution_amount,
            self.rebalancing_dates,
        )

        self.assertRaises(anda.InsufficientTimeframe, lambda: anda.best_year(strategy))
        self.assertRaises(anda.InsufficientTimeframe, lambda: anda.worst_year(strategy))
        self.assertRaises(
            anda.InsufficientTimeframe, lambda: anda.best_year_no(strategy)
        )
        self.assertRaises(
            anda.InsufficientTimeframe, lambda: anda.worst_year_no(strategy)
        )
Esempio n. 7
0
    def test_simple(self):
        start_date = date(1989, 1, 4)
        end_date = date(2010, 1, 1)

        self.msft_vals = self.msft_vals.reindex(
            pd.date_range(start_date, end_date)
        ).ffill()

        assets = [
            anda.Asset("MSFT", Decimal("1.0"), self.msft_vals),
        ]

        strategy = anda.Strategy(
            start_date,
            end_date,
            self.starting_balance,
            assets,
            self.contribution_dates,
            self.contribution_amount,
            self.rebalancing_dates,
        )

        b = anda.best_year(strategy)
        w = anda.worst_year(strategy)

        self.assertAlmostEqual(b, Decimal("120"), delta=2)
        self.assertAlmostEqual(w, Decimal("-63"), delta=2)
        self.assertAlmostEqual(b, Decimal("122"), delta=Decimal("0.5"))
        self.assertAlmostEqual(w, Decimal("-63"), delta=Decimal("0.5"))

        b_year = anda.best_year_no(strategy)
        w_year = anda.worst_year_no(strategy)

        self.assertEqual(b_year, 1991)
        self.assertEqual(w_year, 2000)
Esempio n. 8
0
    def test_sortino_ratio_single_asset(self):
        start_date = date(1986, 12, 31)
        end_date = date(2019, 12, 31)

        msft_vals = self.msft_vals.reindex(pd.date_range(start_date, end_date)).ffill()
        risk_free_vals = (
            self.risk_free_vals.dropna()["Close"]
            .reindex(pd.date_range(start_date, end_date))
            .ffill()
        )

        assets = [anda.Asset("MSFT", Decimal(1.0), msft_vals)]

        strategy = anda.Strategy(
            start_date,
            end_date,
            self.starting_balance,
            assets,
            self.contribution_dates,
            self.contribution_amount,
            self.rebalancing_dates,
        )
        self.assertAlmostEqual(
            anda.sortino_ratio(strategy, risk_free_vals), Decimal("1.34"), delta=0.1
        )
Esempio n. 9
0
def get_strategy(
    tickers,
    proportions,
    handles,
    start_date,
    end_date,
    input_money,
    contribution_amount,
    contribution_dates,
    rebalancing_dates,
):
    """
    Initializes and returns strategy object
    """
    weights = [p for p in proportions if p is not None]
    normalise(weights)

    # Separate user-supplied data from Thalia-known data.
    user_assets = []
    thalia_tickers = []
    thalia_weights = []
    for ticker, weight, handle in zip(tickers, weights, handles):
        if handle is None:
            thalia_tickers.append(ticker)
            thalia_weights.append(weight)
        else:
            user_assets.append((ticker, weight, handle))

    thalia_data = get_assets(thalia_tickers, thalia_weights, start_date,
                             end_date)

    if thalia_data is None:
        # raise error
        return None

    user_supplied_data = [
        anda.Asset(ticker, weight, user_csv.retrieve(handle))
        for ticker, weight, handle in user_assets
    ]
    all_asset_data = user_supplied_data + thalia_data

    real_start_date = max(asset.values.index[0] for asset in all_asset_data)
    real_end_date = min(asset.values.index[-1] for asset in all_asset_data)

    if real_end_date < real_start_date:
        # raise error
        return None

    strategy = anda.Strategy(
        real_start_date,
        real_end_date,
        input_money,
        all_asset_data,
        contribution_dates,
        contribution_amount,
        rebalancing_dates,
    )
    return strategy
Esempio n. 10
0
    def test_max_drawdown_multi_asset(self):
        start_date = date(1989, 12, 29)
        end_date = date(2000, 12, 29)

        msft_vals = self.msft_vals.reindex(pd.date_range(start_date, end_date)).ffill()
        berkshire_vals = self.berkshire_vals.reindex(
            pd.date_range(start_date, end_date)
        ).ffill()

        assets = [
            anda.Asset("MSFT", Decimal(0.6), msft_vals),
            anda.Asset("BRK-A", Decimal(0.4), berkshire_vals),
        ]

        strategy = anda.Strategy(
            start_date,
            end_date,
            self.starting_balance,
            assets,
            self.contribution_dates,
            self.contribution_amount,
            self.rebalancing_dates,
        )
        self.assertAlmostEqual(anda.max_drawdown(strategy), Decimal("59.03"), delta=3)
Esempio n. 11
0
    def test_rebalancing(self):
        # TODO
        starting_balance = Decimal("10000.00")
        contribution_dates = set()
        contribution_amount = Decimal("0.0")
        rebalancing_dates = self.dates

        assets = [
            anda.Asset("GOLD", Decimal("0.5"), self.gold_data),
            anda.Asset("SLV", Decimal("0.5"), self.silver_data),
        ]

        strategy = anda.Strategy(
            self.start,
            self.end,
            starting_balance,
            assets,
            contribution_dates,
            contribution_amount,
            rebalancing_dates,
        )

        roi = anda.total_return(strategy)
        roi  # gotta keep flake8 happy.
Esempio n. 12
0
    def test_max_drawdown_single_asset(self):
        start_date = date(1986, 12, 31)
        end_date = date(2019, 12, 31)

        msft_vals = self.msft_vals.reindex(pd.date_range(start_date, end_date)).ffill()

        assets = [anda.Asset("MSFT", Decimal("1.0"), msft_vals)]

        strategy = anda.Strategy(
            start_date,
            end_date,
            self.starting_balance,
            assets,
            self.contribution_dates,
            self.contribution_amount,
            self.rebalancing_dates,
        )
        self.assertAlmostEqual(anda.max_drawdown(strategy), Decimal("72.33"), delta=2.5)
Esempio n. 13
0
    def test_single_asset(self):
        starting_balance = Decimal("23.46")
        contribution_dates = set()
        contribution_amount = None
        rebalancing_dates = set()

        assets = [anda.Asset("Gold", Decimal("1.0"), self.gold_data)]

        strategy = anda.Strategy(
            self.start,
            self.end,
            starting_balance,
            assets,
            contribution_dates,
            contribution_amount,
            rebalancing_dates,
        )

        roi = anda.total_return(strategy)
        self.assertEqual(roi.at[self.start], Decimal("23.46"))
        self.assertEqual(roi.at[date(2000, 1, 12)], Decimal("24.75"))
        self.assertEqual(roi.at[self.end], Decimal("25.69"))
Esempio n. 14
0
    def test_no_money(self):
        starting_balance = Decimal("0.00")
        contribution_dates = pd.date_range(
            self.start, self.end, freq=timedelta(days=4)
        )[1:]
        contribution_amount = Decimal("1000.00")
        rebalancing_dates = set()

        assets = [anda.Asset("ST", Decimal("1.0"), self.rock_data)]

        strategy = anda.Strategy(
            self.start,
            self.end,
            starting_balance,
            assets,
            contribution_dates,
            contribution_amount,
            rebalancing_dates,
        )

        roi = anda.total_return(strategy)
        roi  # Just the lack of exception *should* be a sign of success.
Esempio n. 15
0
    def test_contribution(self):
        starting_balance = Decimal("1.00")
        contribution_dates = self.dates
        contribution_amount = Decimal("1.00")
        rebalancing_dates = set()

        assets = [anda.Asset("ST", Decimal("1.00"), self.rock_data)]

        strategy = anda.Strategy(
            self.start,
            self.end,
            starting_balance,
            assets,
            contribution_dates,
            contribution_amount,
            rebalancing_dates,
        )

        roi = anda.total_return(strategy)
        self.assertEqual(Decimal("2.00"), roi.at[self.start])
        for (day, next_day) in zip(self.dates, self.dates[1:]):
            self.assertEqual(roi[day] + Decimal("1.00"), roi[next_day])
Esempio n. 16
0
    def test_dividends_single_asset(self):
        start_date = date(1986, 12, 31)
        end_date = date(2019, 12, 31)

        msft_vals = self.msft_vals.reindex(pd.date_range(start_date, end_date)).ffill()
        msft_dividends = self.msft_dividends.reindex(
            pd.date_range(start_date, end_date)
        ).dropna()

        assets = [anda.Asset("MSFT", Decimal("1.0"), msft_vals, msft_dividends)]

        strategy = anda.Strategy(
            start_date,
            end_date,
            self.starting_balance,
            assets,
            self.contribution_dates,
            self.contribution_amount,
            self.rebalancing_dates,
        )
        self.assertAlmostEqual(
            anda.total_return(strategy)[end_date], Decimal("14599199.22"), delta=1
        )