Problem
Ett av mina mål med min TrendValue-portfölj är att den ska berätta för mig när jag behöver agera så att jag slipper drabbas av känslomässiga, felaktiga köp- och sälj-transaktioner och undvika min egen idioti och okunskap, och ett steg i den riktningen är att ha ett glidande Stop-Loss på 20%. Tyvärr går det inte att hos Avanza sätta upp glidande Stop-Loss som gäller tills vidare, utan om jag fattat det rätt (förmodligen inte...) så går det bara att lägga det som en säljorder som gäller upp till 30 dagar. Jag hade ju helst sett att det gick att lägga en trigger eller alarm som är permanent och procentuellt räknad från All Time High sedan inköp, och triggern hos Avanza verkar bara vara som ett fast belopp.
Som den SysAdmin jag är till vardags, så har jag därför försökt lösa uppgiften på egen hand med hjälp av ett Powershell script (JA, det finns bättre skriptspråk. JA, det finns säkert färdiga lösningar på mitt problem. JA, det kan GARANTERAT optimeras. NEJ, det finns inte på GitHub ... jag vet, men jag är nöjd med resultatet och bryr mig inte). Detta är ett as-is-inga-garantier-med-total-avsaknad-av-felhantering-som-potentiellt-kan-formatera-om-Internet-skript, men om du tror att det funkar och aldrig kommer att be mig om hjälp med ev fel, fuckups eller andra fullt möjliga scenarier som kan inträffa så är du VARMT VÄLKOMMEN att använda skriptet. :)
Lösning
I korta drag funkar den så här (jag vet att det är ap-fult, men det fyller sin funktion. Jag har tyvärr inga Powerpoint-skills, så ni får ta det som det är...):- Skriptet körs var 5:e minut (som en Scheduled Task i Windows) och läser in data från CSV-filen med den senaste datan om alla aktierna.
- Aktuell data om aktierna hämtas från Yahoo Finance baserat på ticker.
- Jämförelse mellan nuvarande pris och tidigare All Time High görs och uppdateras om det har stigit.
- CSV-filen uppdateras med ny data.
- Mail skickas OM någon aktie fallit mer än X% från All Time High (för närvarande kör med X=20%, såg en intressant artikel om Stop-Loss)
Text-filen
Semikolonseparerad text-fil med innehaven specificerade i form av:- companyName - namnet på företaget
- ticker - stock ticker hos Yahoo Finance
- price - aktuellt pris på aktien
- allTimeHigh - All Time High pris på aktien sedan inköp, uppdateras vid varje skriptkörning.
- athDeviation - beräknas som ((allTimeHigh - pris)/allTimeHigh * 100) och är den procentuella skillnaden mellan All Time High och det nuvarande priset på aktien. Uppdateras vid varje körning.
- timestamp - tidsangivelse på senaste datat för en aktie, uppdateras vid varje körning
- alertSent - är i utgångsläget satt till FALSE (skrivs manuellt in i filen när man skapar den), men sätts till TRUE om ett mail har skickats angående den aktuella aktien, för att undvika att scriptet mailar var 5:e minut om larm på samma aktie. Flaggan måste återställas till FALSE manuellt, men tanken är ju att man ska sälja aktien istället eftersom GSL har överskridits.
Skriptet
Det är väl inte så mycket att säga om, inga funktioner, inga in-parametrar går att använda... plain and simple, från start till slut."System Requirements" är att filen med aktie-datan finns ($filepath) och att du har tillgång till en SMTP-server/tjänst som går att skicka mailen via. Sedan får man ändra $trailingStopLossLimit till önskat värde, i mitt fall 20%
Det finns två Write-Host rader som skriver ut om allTimeHigh ökat eller är oförändrat, samt en rad i #Export delen som skriver ut allStocks och dess data. Dessa har jag enbart använt när jag byggt skriptet och de syns bara om man kör det i Powershell-konsollen, så de kan tas bort/kommenteras ut, om man schemalägger det. Enjoy!
$alertList = @()
$allStocks = @()
$tempFilePath = "C:\scripts\fin\temp.csv"
$filePath = "C:\scripts\fin\yahoo_stockPrices.csv"
$trailingStopLossLimit = 20 #as percentage
# Get historical data from file
$stocksHistory = Import-Csv -Path $filePath -Delimiter ";"
# Loop through all stocks
foreach($stockHistory in $stocksHistory){
# Construct URL
$baseUrl = "http://finance.yahoo.com/d/quotes.csv?s="
$dataSelection = "&f=snl1c4d1t1" #http://www.jarloo.com/yahoo_finance/, https://greenido.wordpress.com/2009/12/22/yahoo-finance-hidden-api/
$url = $baseUrl + $($stockHistory.Ticker) + $dataSelection
# Get current data from Yahoo Finance to CSV file
Invoke-WebRequest -Uri $url -OutFile $tempFilePath
# Import data from downloaded CSV file
$stockCurrent = Import-Csv $tempFilePath -Delimiter "," -Header Ticker, CompanyName, Price, Currency, Date, Time
# Calculate AllTimeHigh deviation
$athDeviation = ([system.double]$stockHistory.allTimeHigh - [system.double]$stockCurrent.Price)/[system.double]$stockHistory.allTimeHigh * 100
# Compare current Yahoo prices with historical AllTimeHigh
if([system.double]$stockCurrent.Price -gt [system.double]$stockHistory.allTimeHigh){
Write-Host "---$($stockCurrent.CompanyName): All time high exceeded!" -ForegroundColor Green
$stockHistory.allTimeHigh = $stockCurrent.Price
}else{
Write-Host "---$($stockCurrent.CompanyName): All time high NOT exceeded!" -ForegroundColor Yellow
}
# Stop Loss Alert filtering
If(($stockHistory.alertSent -eq $false) -and ($athDeviation -gt $trailingStopLossLimit)){
# Collect current alerts
$alertList += $stockHistory
$stockHistory.alertSent = $true
}
# Update stock with Yahoo Finance data
$stockHistory.price = $stockCurrent.Price
$stockHistory.timeStamp = (get-date ($stockCurrent.Date) -Format yyyy-MM-dd) + "T" + (get-date ($stockCurrent.Time) -Format HH:mm:ss) + "Z"
$stockHistory.athDeviation = $athDeviation
# Save updated stock info
$allStocks += $stockHistory
}
# Export
$allStocks | Export-Csv -Path $filePath -Force -Delimiter ";" -NoTypeInformation
$allStocks | Sort-Object athDeviation -Descending| ft -AutoSize
# Send notfication if there are objects on Alertlist
if($alertlist.count -ne 0){
# Convert AlertList to HTML
$Header = @"
<style>
TABLE {border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}
TH {border-width: 1px;padding: 3px;border-style: solid;border-color: black;background-color: #6495ED;}
TD {border-width: 1px;padding: 3px;border-style: solid;border-color: black;}
</style>
"@
[System.String]$body = $alertList | ConvertTo-HTML -Head $Header
Send-MailMessage -From abc@mail.com -To abc@mail.com -BodyAsHtml -body $body -Subject "Automated Stock Alert" -SmtpServer smtp.mail.com
}

