Vanskelig oppgave

Gjør denne oppgaven hvis du får til de enkle repetisjonsoppgavene.

I denne oppgaven er det en stor fordel å ha matplotlib installert.

Denne opgaven er en litt modifisert versjon av en oppgave som ble gitt på fredagspython i 2018.

Introduksjon

I denne oppgaven skal vi ved hjelp av Python-kode finne ut om det er mulig å tjene penger på å selge og kjøpe en aksje. Vi skal gjøre dette ved å lage et Python-program som forsøker å kjøpe og selge aksjen til Apple gjennom de siste 3 årene, og se om programmet ender opp med å tape eller tjene penger dersom det følger ulike regler for når det lønner seg å kjøpe og selge. Målet er å teste ut ulike strategier og forsøke å "tjene" mest mulig penger.

Vi vil utvikle programmet ved å teste på Apple sin aksjekurs for de siste 3 årene, men etter at vi har funnet en god algoritme vil vi til slutt teste strategien på et annet selskap, for å se om det vi har funnet også fungerer bra generelt (og har potensiale for å fungere fram i tid, ikke bare tilbake i tid).

Start med å laste ned denne filen, som inneholder ett tall for hver dag, som sier hva prisen til Apple sin aksje ble kjøpt/solgt for den dagen. Lagre filen i samme mappe som du skriver Python-programmet.

Oppgave 1

Lag en funksjon les_inn_aksjekurser som tar et filnavn som parameter.

Funksjonen skal åpne filen og lese inn aksjekursene fra den filen og legge dem i en liste. Hver linje i filen inneholder et tall (et flyttall) som er kursen for den dagen.

Kall funksjonen din og print listen. Sjekk at den starter slik:

[66.715714, 66.928574, 67.048569, ...

Det er nyttig å visualisere aksjekursene. Det gjør det enklere å se mønstre som vi kan utnytte i trading-algoritmen vår. Dette gjøres enkelt med python ved å bruke biblioteket matplotliib.

import matplotlib.pyplot as plt
priser = les_inn_aksjekurser(“apple.txt”)
plt.plot(priser)
plt.show()

Du vil se noe slikt som dette:

plott

Før du går videre bør programmet ditt se omtrent slik ut:

import matplotlib.pyplot as plt

def les_inn_akjekurser(filnavn):
   priser = []
   fil = open(filnavn)
   for linje in fil:
       priser.append(float(linje.strip()))

   return priser

priser = les_inn_akjekurser("apple.txt")
plt.plot(priser)
plt.show()

Oppgave 2

Vi har en teori om at det kan lønne seg å kjøpe aksjen når prisen er lavere enn det den har pleid å være i det siste, og selge når prisen er høyere enn det den har pleid å være i det siste (dette er en enkel men ganske vanlig strategi blant aksjetradere).

For å se om dette kan fungere, vil vi for hver dag (hver pris i listen) regne ut gjennomsnittet av prisen de siste 10 dagene.

Lag en funksjon som heter hent_gjennomsnitt_siste_n_dager og som tar to parametere priser og antall_dager. Priser er en liste som inneholder alle aksjekursene dag for dag og antall_dager er et tall som sier hvor mange dager tilbake vi ønsker å regne ut gjennomsnittet.

Funksjonen skal gå gjennom listen av priser, og for hver pris regne ut gjennomsnittet av prisene som har vært de siste antall_dager dagene og lagre alle disse gjennomsnittene i en ny liste.

Obs: For de første dagene vil det ikke gå å hente prisen mange dager tilbake. I den innerste for-løkken bør du ta høyde for dette. Hvis i er større enn dagnummer, så vil jo dagnummer - i bli negativt. I de tilfellene trenger du bare å regne gjennomsnittet av dagene fram til nå.

Når du har skrevet ferdig denne funksjonen, bør du kunne kjøre dette og få et plott som det under (plottet er zoomet inn litt):

priser = les_inn_akjekurser("apple.txt")
gjennomsnittspriser = hent_gjennomsnitt_siste_n_dager(priser, 10)
plt.plot(priser)
plt.plot(gjennomsnittspriser)
plt.show()

plott

Oppgave 3

Vi er nå klare til å prøve å kjøpe og selge aksjen ved å følge en regel, og se om vi tjener penger på det.

Planen vår er:

Bildet viser eksempler på to sett med kjøp og salg:

plott

Lag en funksjon kjop_og_selg(priser, gjennomsnittspriser) som tar inn de to listene som inneholder prisene for hver dag og gjennomsnittsprisene for de siste 10 dagene.

I funksjonene går du gjennom dag for dag med en for-løkke, og sjekker om du skal kjøpe eller selge (vi starter for-løkken på dag nr. 10 for enkelhetsskyld, det har ikke så mye å si):

for i in range(10, len(priser):
	# Sjekk om vi skal kjøpe eller selge

Vi ønsker alltid å kjøpe og selge annenhver gang. Du kan altså ikke ha kjøpt og så kjøpe igjen noen dager senere uten å ha solgt i mellomtiden. Derfor må du ha en variabel på utsiden av for-løkken som holder orden på om du nå har noe som kan selges eller ikke. En måte å gjøre dette på er slik:

har_kjopt =  False
for i in range(10, len(priser):
	if … sjekk om vi skal kjøpe … and not har_kjopt:
		# Kjøp
	elif … sjekk om vi skal selge her …:
		# Selg

Hver gang vi kjøper ønsker vi å lagre prisen vi kjøpte for i en variabel. Når vi selger, så ønsker vi å regne ut forskjellen på prisen nå og det prisen var sist gang vi kjøpte. Denne differansen legger plusser vi på en variabel som holder på fortjenesten vår (vi antar her at vi selger og kjøper én aksje hver gang). Til slutt ønsker vi å printe ut den totale fortjenesten.

Print gjerne ut noe tekst hver gang du kjøper og selger og hva prisen er på da. Det gjør det enklere å se om det skjer noen feil.

Om alt fungerer som det skal bør du få ut noe slikt som dette (viser bare slutten av mulig output):

Kjoper til prisen 188.770
Solgte til prisen 191.550
Tjent paa denne handelen: 2.780 
Kjoper til prisen 186.290
Solgte til prisen 183.820
Tjent paa denne handelen: -2.470 
Kjoper til prisen 187.790
Solgte til prisen 189.690
Tjent paa denne handelen: 1.900 
Kjoper til prisen 191.780
Solgte til prisen 191.900
Tjent paa denne handelen: 0.120 
Kjoper til prisen 199.130
Solgte til prisen 221.850
Tjent paa denne handelen: 22.720 
Tjent totalt: 111.036

Forbedre algoritmen din

Regelen vi bruker nå er veldig enkel. Test gjerne ut andre strategier. Du kan for eksempel prøve å se på mer eller mindre enn de 10 siste dagene når du regner gjennomsnittet.

En annen ting som ofte gir bedre resultater er å bruke et vektet gjennomsnitt der du f. eks tar gjennomsnittet av de 3 siste dagene og de 10 siste dagene og slår sammen, men vekter de siste 3 mer (for eksempel 0.7 * gjennomsnitt for 3 siste dagene + 0.3 * gjennomsnitt for 10 siste dagene).

Det er som sagt mange mulige strategier. Vær kreativ, så finner du kanskje noe som fungerer bra!

PS: