Categories
blandet

Hent transaktioner ud af Nordnet – med PowerShell!

Jeg blev spurgt om man kan få mit Python-program til at hente transaktioner ud af Nordnet oversat til PowerShell. Det kan man, dog i en lidt mere rudimentær version. Her er kode til login i Nordnet og hentning af transaktionsdata for en enkelt konto/portefølje. For at få scriptet til at virke, skal du indsætte nogle værdier de rigtige steder i scriptet:

  • brugernavn og password til Nordnet
  • til- og fradato, du vil hente transaktioner for
  • kontonummer på den konto i Nordnet, du vil hente fra (din første konto har kontonummer 1 osv.

Her er koden:

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$url = 'https://classic.nordnet.dk/mux/login/start.html?cmpi=start-loggain&state=signin'
$r1 = iwr $url -SessionVariable cookies
 
$url = 'https://classic.nordnet.dk/api/2/login/anonymous/'
$r2 = iwr $url -method 'POST' -Headers @{'Accept' = '*/*'} -WebSession $cookies
 
$body = @{'username'=''; 'password'=''}
$url = 'https://classic.nordnet.dk/api/2/authentication/basic/login'
$r3 = iwr $url -method 'POST' -Body $body -Headers @{'Accept' = '*/*'} -WebSession $cookies
 
$url = 'https://classic.nordnet.dk/oauth2/authorize?client_id=NEXT&response_type=code&redirect_uri=https://www.nordnet.dk/oauth2/'
$r4 = iwr $url -WebSession $cookies
 
$url = 'https://www.nordnet.dk/mediaapi/transaction/csv/filtered?locale=da-DK&account_id=1&from=2019-08-01&to=2019-10-01'
$r5 = iwr $url -WebSession $cookies

$content = $r5.Content
$encoding = [System.Text.Encoding]::unicode
$bytes = $encoding.GetBytes($content)

$decoded_content = [System.Text.Encoding]::utf32.GetString($bytes)
$decoded_content = $decoded_content.Substring(1,$decoded_content.length-1)
Categories
blandet

Hiv dine transaktioner ud af det nye Nordnet

Her er en opdatering af mit gamle program til at hente transaktioner ud fra Nordnet. Det er opdateret til at fungere med Nordnets nye design og API:

# -*- coding: utf-8 -*-
# Author: Morten Helmstedt. E-mail: helmstedt@gmail.com
""" This program logs into a Nordnet account and extracts transactions as a csv file.
Handy for exporting to Excel with as few manual steps as possible """

import requests 
from datetime import datetime
from datetime import date

# USER ACCOUNT, PORTFOLIO AND PERIOD DATA. SHOULD BE EDITED FOR YOUR NEEDS #

# Nordnet user account credentials and accounts/portfolios names (choose yourself) and numbers.
# To get account numbers go to https://www.nordnet.dk/transaktioner and change
# between accounts. The number after "accid=" in the new URL is your account number.
# If you have only one account, your account number is 1.
user = ''
password = ''
accounts = {
	"Frie midler: Nordnet": "1",
	"Ratepension": "3",
}

# Start date (start of period for transactions) and date today used for extraction of transactions
startdate = '2013-01-01'
today = date.today()
enddate = datetime.strftime(today, '%Y-%m-%d')

# Manual data lines. These can be used if you have portfolios elsewhere that you would
# like to add manually to the data set. If no manual data the variable manualdataexists
# should be set to False
manualdataexists = True
manualdata = """
Id;Bogføringsdag;Handelsdag;Valørdag;Transaktionstype;Værdipapirer;Instrumenttyp;ISIN;Antal;Kurs;Rente;Afgifter;Beløb;Valuta;Indkøbsværdi;Resultat;Totalt antal;Saldo;Vekslingskurs;Transaktionstekst;Makuleringsdato;Verifikations-/Notanummer;Depot
;30-09-2013;30-09-2013;30-09-2013;KØBT;Obligationer 3,5%;Obligationer;;72000;;;;-69.891,54;DKK;;;;;;;;;;Frie midler: Finansbanken
"""

# CREATE VARIABLES FOR LATER USE. #

# Creates a dictionary to use with cookies	
cookies = {}

# A variable to store transactions before saving to csv
transactions = ""

# LOGIN TO NORDNET #

# First part of cookie setting prior to login
url = 'https://classic.nordnet.dk/mux/login/start.html?cmpi=start-loggain&state=signin'
request = requests.get(url)
cookies['LOL'] = request.cookies['LOL']
cookies['TUX-COOKIE'] = request.cookies['TUX-COOKIE']

# Second part of cookie setting prior to login
url = 'https://classic.nordnet.dk/api/2/login/anonymous'
request = requests.post(url)
cookies['NOW'] = request.cookies['NOW']

# Actual login that gets us cookies required for later use
url = 'https://classic.nordnet.dk/api/2/authentication/basic/login'
request = requests.post(url,cookies=cookies, data = {'username': user, 'password': password})
cookies['NOW'] = request.cookies['NOW']
cookies['xsrf'] = request.cookies['xsrf']

# Getting a NEXT cookie
url = 'https://classic.nordnet.dk/oauth2/authorize?client_id=NEXT&response_type=code&redirect_uri=https://www.nordnet.dk/oauth2/'
request = requests.get(url, cookies=cookies)
cookies['NEXT'] = request.history[1].cookies['NEXT']

# GET TRANSACTION DATA #

# Payload and url for transaction requests
payload = {
'locale': 'da-DK',
'from': startdate,
'to': enddate,
}

url = "https://www.nordnet.dk/mediaapi/transaction/csv/filtered"

firstaccount = True
for portfolioname, id in accounts.items():
	payload['account_id'] = id
	data = requests.get(url, params=payload, cookies=cookies)
	result = data.content.decode('utf-16')
	result = result.replace('\t',';')

	result = result.splitlines()
	
	firstline = True
	for line in result:
		# For first account and first line, we use headers and add an additional column
		if line and firstline == True and firstaccount == True:
			transactions += line + ';' + "Depot" + "\n"
			firstaccount = False
			firstline = False
		# First lines of additional accounts are discarded
		elif line and firstline == True and firstaccount == False:
			firstline = False
		# Content lines are added
		elif line and firstline == False:
			# Fix because Nordnet sometimes adds one empty column too many
			if line.count(';') == 23:
				line = line.replace('; ',' ')
			transactions += line + ';' + portfolioname + "\n"

# ADD MANUAL LINES IF ANY #
if manualdataexists == True:
	manualdata = manualdata.split("\n",2)[2]
	transactions += manualdata

# Saves CSV
with open("transactions.csv", "w", encoding='utf8') as fout:
	fout.write(transactions)

Categories
blandet

Hent kurser – historiske og realtid – på dine værdipapirer i det nye Nordnet

Nordnet har fået nyt design og ny API. Det betyder, at der skal lidt flere krumspring til end tidligere, når man skal have fat på kurser på sine værdipapirer.

Her er et program i Python, der kan hjælpe dig. Det kræver login til Nordnet.

# -*- coding: utf-8 -*-
# Author: Morten Helmstedt. E-mail: helmstedt@gmail.com
""" This program extracts historical stock prices from Nordnet (and Morningstar as a fallback) """

import requests
from datetime import datetime
from datetime import date
import os

# Nordnet user account credentials
user = ''
password = ''

# DATE AND STOCK DATA. SHOULD BE EDITED FOR YOUR NEEDS #

# Start date (start of historical price period)
startdate = '2013-01-01'

# List of shares to look up prices for.
# Format is: Name, Morningstar id, Nordnet stock identifier
# See e.g. https://www.nordnet.dk/markedet/aktiekurser/16256554-novo-nordisk-b
# (identifier is 16256554)
# All shares must have a name (whatever you like). To get prices they must
# either have a Nordnet identifier or a Morningstar id
sharelist = [
["Maj Invest Pension","F0GBR064UH",16099877],
["Novo Nordisk B A/S","0P0000A5BQ",16256554],
["Nordnet Superfonden Danmark","F00000TH8X",""],
]

# CREATE VARIABLES FOR LATER USE. #

# A variable to store historical prices before saving to csv	
finalresult = ""
finalresult += '"date";"price";"instrument"' + '\n'

# A cookie dictionary for storing cookies
cookies = {}

# NORDNET LOGIN #

# First part of cookie setting prior to login
url = 'https://classic.nordnet.dk/mux/login/start.html?cmpi=start-loggain&state=signin'
request = requests.get(url)
cookies['LOL'] = request.cookies['LOL']
cookies['TUX-COOKIE'] = request.cookies['TUX-COOKIE']

# Second part of cookie setting prior to login
url = 'https://classic.nordnet.dk/api/2/login/anonymous'
request = requests.post(url, cookies=cookies)
cookies['NOW'] = request.cookies['NOW']

# Actual login that gets us cookies required for later use
url = "https://classic.nordnet.dk/api/2/authentication/basic/login"
request = requests.post(url,cookies=cookies, data = {'username': user, 'password': password})
cookies['NOW'] = request.cookies['NOW']
cookies['xsrf'] = request.cookies['xsrf']

# Getting a NEXT cookie
url = "https://classic.nordnet.dk/oauth2/authorize?client_id=NEXT&response_type=code&redirect_uri=https://www.nordnet.dk/oauth2/"
request = requests.get(url, cookies=cookies)
cookies['NEXT'] = request.history[1].cookies['NEXT']

# LOOPS TO REQUEST HISTORICAL PRICES AT NORDNET AND MORNINGSTAR #

# Nordnet loop to get historical prices
for share in sharelist:
	# Nordnet stock identifier and market number must both exist
	if share[2]:
		url = "https://www.nordnet.dk/api/2/instruments/historical/prices/" + str(share[2])
		payload = {"from": startdate, "fields": "last"}
		data = requests.get(url, params=payload, cookies=cookies)
		jsondecode = data.json()
		
		# Sometimes the final date is returned twice. A list is created to check for duplicates.
		datelist = []
		
		for value in jsondecode[0]['prices']:
			price = str(value['last'])
			price = price.replace(".",",")
			date = datetime.fromtimestamp(value['time'] / 1000)
			date = datetime.strftime(date, '%Y-%m-%d')
			# Only adds a date if it has not been added before
			if date not in datelist:
				datelist.append(date)
				finalresult += '"' + date + '"' + ";" + '"' + price + '"' + ";" + '"' + share[0] + '"' + "\n"

# Morningstar loop to get historical prices			
for share in sharelist:
	# Only runs for one specific fund in this instance
	if share[0] == "Nordnet Superfonden Danmark":
		payload = {"id": share[1], "currencyId": "DKK", "idtype": "Morningstar", "frequency": "daily", "startDate": startdate, "outputType": "COMPACTJSON"}
		data = requests.get("http://tools.morningstar.dk/api/rest.svc/timeseries_price/nen6ere626", params=payload)
		jsondecode = data.json()
		
		for lists in jsondecode:
			price = str(lists[1])
			price = price.replace(".",",")
			date = datetime.fromtimestamp(lists[0] / 1000)
			date = datetime.strftime(date, '%Y-%m-%d')
			finalresult += '"' + date + '"' + ";" + '"' + price + '"' + ";" + '"' + share[0] + '"' + "\n"

# WRITE CSV OUTPUT TO FILE #			

with open("kurser.csv", "w", newline='', encoding='utf8') as fout:
	fout.write(finalresult)