Basis

Deze pagina bevat uitvoerbare code.

TR investeringen BV

Elke stap staat hieronder in een cel die bij de build wordt uitgevoerd, met de tests uit de opgave eronder. Alleen het menuprogramma van stap 11 draait niet mee: dat vraagt om invoer van de gebruiker en zou de build laten wachten.

Stap 1: print_prices(prices)

def print_prices(prices):
    """Drukt de prijzen af als tabel met een kolom Dag en een kolom Prijs."""
    print(f"{'Dag':>4}  {'Prijs':>7}")
    print(f"{'---':>4}  {'-----':>7}")
    for day in range(len(prices)):
        print(f"{day:>4}  {prices[day]:>7.2f}")
print_prices([20, 10, 30])
 Dag    Prijs
 ---    -----
   0    20.00
   1    10.00
   2    30.00

Stap 2: mean(prices)

def mean(prices):
    """Geeft de gemiddelde prijs van de niet-lege lijst prices terug."""
    total = 0
    for price in prices:
        total = total + price
    return total / len(prices)
assert mean([20, 10, 30]) == 20.0
assert mean([5]) == 5.0
assert mean([1, 2]) == 1.5

Stap 3: std_dev(prices)

def std_dev(prices):
    """Geeft de standaardafwijking van de niet-lege lijst prices terug."""
    avg = mean(prices)
    total = 0
    for price in prices:
        total = total + (price - avg) ** 2
    return (total / len(prices)) ** 0.5
assert std_dev([20, 10, 30]) == 8.16496580927726
assert std_dev([5]) == 0.0
assert std_dev([10, 10, 10]) == 0.0

Stap 4: find_min(prices)

def find_min(prices):
    """Geeft de laagste prijs terug en de dag waarop die viel."""
    min_price = prices[0]
    min_day = 0
    for day in range(len(prices)):
        if prices[day] < min_price:
            min_price = prices[day]
            min_day = day
    return min_price, min_day
assert find_min([20, 10, 30]) == (10, 1)
assert find_min([7]) == (7, 0)
assert find_min([4, 4, 9]) == (4, 0)

Stap 5: find_max(prices)

def find_max(prices):
    """Geeft de hoogste prijs terug en de dag waarop die viel."""
    max_price = prices[0]
    max_day = 0
    for day in range(len(prices)):
        if prices[day] > max_price:
            max_price = prices[day]
            max_day = day
    return max_price, max_day
assert find_max([20, 10, 30]) == (30, 2)
assert find_max([7]) == (7, 0)
assert find_max([9, 4, 9]) == (9, 0)

Stap 6: best_trade(prices)

def best_trade(prices):
    """Geeft de koopdag, de verkoopdag en de grootste winst terug.

    De verkoopdag ligt nooit vóór de koopdag. Is er geen winst te maken,
    dan is de winst 0 en zijn beide dagen 0.
    """
    buy_day = 0
    sell_day = 0
    best = 0

    for ix1 in range(len(prices)):
        for ix2 in range(ix1, len(prices)):
            profit = prices[ix2] - prices[ix1]
            if profit > best:
                best = profit
                buy_day = ix1
                sell_day = ix2

    return buy_day, sell_day, best
assert best_trade([20, 10, 30]) == (1, 2, 20)
assert best_trade([40, 80, 10, 30, 27, 52, 5, 15]) == (2, 5, 42)
assert best_trade([30, 20, 10]) == (0, 0, 0)
assert best_trade([7]) == (0, 0, 0)

Stap 7: add_fund(grid, prices)

def add_fund(grid, prices):
    """Geeft een nieuw koersenraster terug met prices erbij als extra fonds.

    Elke rij van het raster telt evenveel dagen. Is het raster nog leeg, dan
    bepaalt prices het aantal dagen; anders worden alleen de eerste dagen
    overgenomen. Het raster dat je meegeeft verandert niet.
    """
    if len(grid) == 0:
        n_days = len(prices)
    else:
        n_days = len(grid[0])

    new_row = []
    for day in range(n_days):
        new_row = new_row + [prices[day]]

    return grid + [new_row]
assert add_fund([], [20, 10, 30]) == [[20, 10, 30]]
assert add_fund([[20, 10, 30]], [15, 25, 35]) == [[20, 10, 30], [15, 25, 35]]
assert add_fund([[1, 2]], [7, 8, 9]) == [[1, 2], [7, 8]]

# het raster dat je meegeeft blijft ongewijzigd
grid = [[20, 10, 30]]
add_fund(grid, [15, 25, 35])
assert grid == [[20, 10, 30]]

Stap 8: print_grid(grid)

def print_grid(grid):
    """Drukt het koersenraster af, met een regel per fonds en de dagen als kolommen."""
    print(f"{'fonds':>6}", end="")
    for day in range(len(grid[0])):
        print(f"{day:>8}", end="")
    print()

    for fund in range(len(grid)):
        print(f"{fund:>6}", end="")
        for day in range(len(grid[0])):
            print(f"{grid[fund][day]:>8}", end="")
        print()
print_grid([[20, 10, 30], [15, 25, 35]])
 fonds       0       1       2
     0      20      10      30
     1      15      25      35

Stap 9: mean_per_fund(grid)

def mean_per_fund(grid):
    """Geeft een lijst terug met de gemiddelde koers per fonds, op volgorde van de rijen."""
    means = []
    for fund in range(len(grid)):
        means = means + [mean(grid[fund])]
    return means
assert mean_per_fund([[20, 10, 30], [15, 25, 35]]) == [20.0, 25.0]
assert mean_per_fund([[5, 5]]) == [5.0]

Stap 10: chart(grid, limit)

def chart(grid, limit):
    """Geeft een nieuw raster van tekens terug: # waar de koers minstens limit is, anders een punt."""
    new_grid = []
    for fund in range(len(grid)):
        new_row = []
        for day in range(len(grid[0])):
            if grid[fund][day] >= limit:
                new_row = new_row + ["#"]
            else:
                new_row = new_row + ["."]
        new_grid = new_grid + [new_row]
    return new_grid
assert chart([[20, 10, 30], [15, 25, 35]], 20) == [["#", ".", "#"], [".", "#", "#"]]
assert chart([[1]], 0) == [["#"]]
assert chart([[1]], 2) == [["."]]

Stap 11: main()

Deze cel draagt skip-execution: main vraagt om invoer en eindigt niet uit zichzelf, dus hij kan bij de build niet draaien. Alle functies die hij aanroept staan hierboven wél in cellen die draaien.

def main():
    """De lus voor gebruikersinteractie van het TRI-programma."""
    prices = [20, 10, 30]
    grid = []
    limit = 20

    while True:
        print_menu()
        choice = input("Maak je keuze: ")

        if choice == "9":
            break

        elif choice == "0":
            prices = read_prices()

        elif choice == "1":
            print_prices(prices)

        elif choice == "2":
            print("De gemiddelde prijs is", mean(prices))

        elif choice == "3":
            print("De standaardafwijking is", std_dev(prices))

        elif choice == "4":
            min_price, min_day = find_min(prices)
            print("Het minimum is", min_price, "op dag", min_day)

        elif choice == "5":
            max_price, max_day = find_max(prices)
            print("Het maximum is", max_price, "op dag", max_day)

        elif choice == "6":
            buy_day, sell_day, profit = best_trade(prices)
            print("Je TRI investeringsstrategie is om")
            print("Te kopen op dag", buy_day, "voor prijs", prices[buy_day])
            print("Te verkopen op dag", sell_day, "voor prijs", prices[sell_day])
            print("Dit geeft een totale winst van", profit)

        elif choice == "7":
            grid = add_fund(grid, prices)
            print("Het raster telt nu", len(grid), "fondsen")

        elif choice == "8":
            if len(grid) == 0:
                print("Het raster is nog leeg; voeg eerst een fonds toe met optie 7.")
            else:
                print_grid(grid)
                print("Gemiddelde per fonds:", mean_per_fund(grid))
                print_grid(chart(grid, limit))

        else:
            print()
            print("Optie", choice, "bestaat niet.")
            print("Probeer het opnieuw")

    print()
    print("Tot gisteren!")


def print_menu():
    """Drukt het menu af."""
    print()
    print("(0) Voer een nieuwe lijst prijzen in")
    print("(1) Druk de huidige lijst af")
    print("(2) Bepaal de gemiddelde prijs")
    print("(3) Bepaal de standaardafwijking")
    print("(4) Bepaal het minimum en de bijbehorende dag")
    print("(5) Bepaal het maximum en de bijbehorende dag")
    print("(6) Je TR-investeringsplan")
    print("(7) Voeg de huidige lijst toe als extra fonds")
    print("(8) Toon het koersenraster")
    print("(9) Stoppen")
    print()


def read_prices():
    """Vraagt de gebruiker om prijzen, dag voor dag, en geeft ze terug als lijst getallen."""
    n_days = int(input("Voor hoeveel dagen wil je prijzen invoeren? "))
    prices = []
    for day in range(n_days):
        prices = prices + [float(input(f"Prijs voor dag {day}: "))]
    return prices


main()

De voorbeeldsessie

Wat main doet is een aaneenschakeling van de functies hierboven. Die keten draait hier wel, met de lijst uit de voorbeeldsessie van de opgave.

# De voorbeeldsessie uit de opgave: de gebruiker voert [20, 10, 30] in en
# kiest daarna 1 tot en met 8. Dit is precies de sessie waarop de vorige
# uitwerking vastliep, omdat de prijzen toen strings waren in plaats van getallen.
prices = [20, 10, 30]

print_prices(prices)
print("De gemiddelde prijs is", mean(prices))
print("De standaardafwijking is", std_dev(prices))
print("Het minimum is", find_min(prices))
print("Het maximum is", find_max(prices))
print("Het investeringsplan is", best_trade(prices))

grid = add_fund([], prices)
grid = add_fund(grid, [15, 25, 35])
print_grid(grid)
print("Gemiddelde per fonds:", mean_per_fund(grid))
print_grid(chart(grid, 20))
 Dag    Prijs
 ---    -----
   0    20.00
   1    10.00
   2    30.00
De gemiddelde prijs is 20.0
De standaardafwijking is 8.16496580927726
Het minimum is (10, 1)
Het maximum is (30, 2)
Het investeringsplan is (1, 2, 20)
 fonds       0       1       2
     0      20      10      30
     1      15      25      35
Gemiddelde per fonds: [20.0, 25.0]
 fonds       0       1       2
     0       #       .       #
     1       .       #       #