Tag: "coding"

JOINs

Posted on Jul 31, 2006 von in SQL Server

Einer der effizientesten Wege, um die JOIN Performance zu erhöhen ist die Anzahl der Zeilen die geJOINt werden, zu beschränken. Dies gilt insbesondere für die äußere(n) Tabelle(n) eines JOINs. Es sollten nur die Zeilen zurückgegeben werden, die auch für den JOIN verwendet werden.

Ganze Geschichte »

Pro SQL Server 2005 T-SQL Recipes

Posted on Mär 6, 2006 von in Vermischtes

Die Online Hilfe des SQL Servers (Books Online, aka BOL) ist eine technische Dokumentation, die an Umfang und Ausführlichkeit kaum Wünsche offenläßt. Nahezu alles, was man zum SQL Server wissen muß und will, wird in BOL erklärt. Man muß "nur" wissen, wie man an diese Informationen gelangt.

Ganze Geschichte »

Nominalzins aus Effektivzins errechnen

Posted on Jan 30, 2006 von in SQL Server

Wie man die effektive Verzinsung aus der Nominalverzinsung errechnet, haben wir in diesem Beitrag gesehen. Neulich hat mich aber ein Posting in den MSDN Newsgroups auf die Excel Funktion NOMINAL() aufmerksam gemacht, die genau das Gegenteil macht. Also die Errechnung der Nominalverzinsung bei gegebenem Effektivzins. Um es leichter nachvollziehbar zu machen, verwenden wir die Gegebenheiten aus dem oben bereits referenzierten Beitrag.
Zur Erinnerung: Der von uns errechnete jährliche effektive Zinssatz lag bei 20,27% bei 12 Zinszeitpunkten im Jahr. Also, monatlicher Zins. Diese beiden Angaben (Effektivzins, Perioden) benötigen wir, um daraus den Nominalzinssatz errechnen zu können. Dies geschieht nun folgendermassen:

DECLARE @apr FLOAT
DECLARE @frequency FLOAT

SET @apr = 20.270504548765487/100
SET @frequency = 12

SELECT @frequency * POWER(1+@apr, 1/@frequency)-@frequency AS Nominal_Jahreszins

Nominal_Jahreszins
--------------------
0.18599999999999994

(1 row(s) affected)

In Excel würde das Ganze so

=NOMINAL(A1;A2)

aussehen, wobei in Zelle A1 der Zinssatz und in Zelle A2 die Anzahl der Perioden stehen würde.

2 Kommentare »

JOIN Hints

Posted on Dez 26, 2005 von in SQL Server

JOIN Hints können in einer Abfrage verwendet werden, um den JOIN Typ festzulegen, den der Query Optimiser für den Ausführungsplan verwenden soll: Folgende JOIN Optionen stehen zur Verfügung:
- Loop
- Merge
- Hash

Die Syntax für einen JOIN Hint ist (am Beispiel eines INNER JOINs):

FROM tabelle_1 INNER (LOOP | MERGE | HASH) JOIN tabelle_2

Hier ist ein Beispiel:

FORM header_tabelle INNER LOOP JOIN detail_tabelle

Wie man sehen kann, wird der JOIN Hint zwischen der Angabe des JOIN Typs (hier der INNER) und dem JOIN Schlüsselwort. Nur ein JOIN Hint kann zu einer Zeit pro JOIN in einer Abfrage verwendet werden. Ferner können JOIN Hints nur verwenden werden zusammen mit der ANSI JOIN Syntax, nicht mit der älteren Microsoft JOIN Syntax.

Die obige Syntax ist nicht die einzige Möglichkeit, um einen JOIN Hint in einer Abfrage zu verwenden. Man kann auch die OPTION Klausel verwenden. Diese bewirkt, daß der Hint während der gesamten Abfrage verwendet wird. Es können mehrere Hints in der OPTION Klausel auftauchen, jeder Hint jedoch nur genau 1x. Es gibt nur eine OPTION Klausel pro Abfrage.

Hier ist ein Beispiel der Verwendung der OPTION Klausel:
OPTION (INNER) oder OPTION (MERGE) oder OPTION (HASH)

Welche Methode SQL Server verwendet, um Tabellen zu joinen, hängt von zahlreichen Einzelfaktoren ab. In der Mehrzahl der Fälle wird man aber einen Nested Loop Join beobachten. Bevor man nun aber hingeht, und versucht, den JOIN durch Einsatz eines Hints zu beeinflußen, sollte man immer erst die zugrundeliegende Abfrage und die Indexes auf den zugrundeliegenden Tabellen betrachten und versuchen, diese zu optimieren, bevor man SQL Server durch den Hint in seinem Spielraum einengt und die Verarbeitungsmethode starr vorgibt. Unter Umständen kann man durch den Einsatz des Hints die Performance in den Keller ziehen, wenn z.B. unter geänderten Rahmenbedingungen der Hint nicht mehr angebracht ist; SQL Server jedoch gezwungen ist, diesen zu beachten. Von daher sollte man stets vorher unter realistischen Bedingungen testen, ob der Hint das bringt, was man erwartet.

*****

Die deutsche 30/360 Zinsberechnungsmethode

Posted on Nov 3, 2005 von in SQL Server

In den guten alten Tagen als Computer noch kaum vorhanden und noch weniger leistungsfähig waren, entwickelte sich die deutsche Zinsberechnungsmethode. Die Hauptbesonderheit dieser Methode besteht darin, daß jeder Monat fiktiv 30 Tage hat. Egal, wie viele Tage dieser Monat tatsächlich hat. Das Jahr hatte 360 Tage, egal ob Schaltjahr oder nicht. Dies vereinfachte natürlich die Zinsberechnungen, die damals manuell vorgenommen wurden, enorm. Die Ungleichmäßigkeiten dieser Methode sind mehr oder weniger signifikant. Gerade bei kürzeren Laufzeiten von Wertpapieren wirken sie sich jedoch deutlicher aus als bei längeren.

Mit Einführung des Euros hat man sich entschlossen, auf die ISMA-Regel 251 umzustellen. Diese Regel bezeichnet man auch als act/act Zinsberechnungsmethode. Sie berücksichtigt die tatsächliche Anzahl der Tage. Sowohl im Zähler als auch im Nenner. Mit Beginn der Doppelwährungsphase wurden viele der alten Wertpapieremissionen, die noch mit 30/360 berechnet wurden, Zug um Zug auf die neue Methode umgestellt. Neuemissionen auf dem Kapitalmarkt im Euroland finden in aller Regel heute nur noch mit act/act Regelung statt. Nichtsdestotrotz ist die 30/360 Regel in vielen (ausländischen) Märkten und Marktsegmenten noch präsent. Der amerikanische Kapitalmarkt wendet auch heute noch diese Regeln an. Allerdings mit einer Abweichung zur deutschen Regelung. In den USA wird der 31. eines Tages unter bestimmten Umständen mitgezählt. Die Amerikaner behandeln auch den Februar etwas anders, aber da wir im folgenden diese amerikanische Variante komplett aussen vor lassen interessieren uns diese Besonderheiten jetzt nicht. Wir sprechen hier nur von der deutschen Variante.

Frage: Wie viele Tage liegen zwischen dem 01.11.2005 und dem 01.12.2005?
Antwort: 30

Frage: Wie viele Tage liegen zwischen dem 01.11.2005 und dem 01.01.2006?
Antwort: 60

Frage: Wie viele Tage liegen zwischen dem 28.02.2005 und dem 01.03.2005?
Antwort: 3

Bevor jetzt jemand aufschreit. Stop, wir rechnen jeden Tag fiktiv mit 30 Tagen ab. Also hat auch der Februar 30 fiktive Tage. Somit liegen der 28.02.2005, der 29.02.2005 und der 30.02.2005 gemäß 30/360 Regelung zwischen beiden Tagen und somit ist 3 die richtige Antwort.

Dies ist etwas gewöhnungsbedürftig, aber korrekt. Vielleicht noch ein abschließendes Beispiel.

Frage: Wie viele Tage liegen zwischen dem 30.12.2005 und dem 31.12.2005?
Antwort: 0

Auch hier erst einmal in Ruhe nachdenken, bevor man protestiert. Gemäß unserer Konvention hat jeder Monat 30 Tage. Bei den Monaten mit 31 Tagen wird der 31. künstlich eliminiert. Somit reduziert sich diese Frage auf die Anzahl der Tage, die zwischen dem 30.12.2005 und dem 30.12.2005 liegen. Offensichtlich lautet die richtige Antwort 0.

Genug der Beispiele. Wir suchen nun also einen Algorithmus der dies abbildet.

DECLARE @dt_Start DATETIME
DECLARE @dt_Ende DATETIME
SELECT @dt_Start = '20051101', @dt_Ende = '20051201'
SELECT
DATEDIFF(MONTH, @dt_Start, @dt_Ende) * 30
+ DAY(@dt_Ende)
- DAY(@dt_Start)
- CASE WHEN DAY(@dt_Ende) = 31 THEN 1 ELSE 0 END AS [Tage30/360]

Tage30/360
-----------
30

(1 row(s) affected)

Betrachten wir einmal etwas näher dieses Statement.

Wir multiplizieren die Anzahl der Monate zwischen Ausgangs- und Enddatum mit 30 und eliminieren damit nahezu sämtliche Probleme mit den tatsächlichen Monatstagen. Anschließend addieren wir einfach die Tage des Enddatums hinzu und ziehen die Tage des Startdatums wieder ab. Auf diese Weise eliminieren wir das Problem, wenn das Startdatum nicht auch gleich einem Monatsanfang ist. Zum Schluß müssen wir noch das Problem adressieren wenn das Enddatum auf einen 31. fällt. Dies erfolgt durch den CASE Ausdruck, der bei Bedarf nochmal einen Tag subtrahiert.

Vielleicht noch einige Anmerkungen zur generellen Methodik. Vielfach kann man die wirresten Aussagen lesen, welche Tage nun verzinst werden und welche nicht mehr mitverzinst werden. Wird direkt der 1 Tag inklusive gerechnet oder nicht? Und was ist mit dem letzten Tag? Fakt ist, daß auf keinen Fall beide Tage eingerechnet werden.

Und zumindest im Wertpapiergeschäft ist es üblich, den 1. Tag einer Zinsperiode mitzuverzinsen, während der letzte Tag nicht mitverzinst wird. Dies mag in anderen Bereichen, wie bei der Berechnung von Verzugszinsen oder KK Krediten anders sein, wer aber dies auch für den Wertpapierbereich behauptet, mag sich mal in Ruhe Wertpapierurkunden von Banken durchlesen. Diese sind selbst für juristische Laien unzweideutig. Beginnend mit der Valutierung  (einschließlich) bis zum Tag der nächsten Kuponzahlung (ausschließlich) werden Zinsen gerechnet.

Eigentlich ganz einfach und auch logisch, aber immer wieder ein beliebtes Thema bei der Ermittlung von Zinsabgrenzungen im Rahmen des Jahresabschlusses. Wir hatten jahrelang Spaß mit unserer Wirtschaftsprüfungsgesellschaft. Da mit Ausnahme des Prüfungsleiters das Team fast jedes Jahr wechselte, konnte man dies den neuen Prüfern immer wieder erklären.

Warum dieser Beitrag, die deutsche Zinsberechnungsmethode spielt doch, gerade im europäischen Wertpapierhandel, kaum noch eine Rolle?

Nun, in den letzten Tagen habe ich mich entschlossen, meine T-SQL Implementierung der Yield-to-maturity (YTM) Berechnung als Beitrag zu veröffentlichen. Ein Faktor bei der YTM Bestimmung ist die anzusetzende Zinsberechnungsmethode, zu der dieser Beitrag das grundlegende Verständnis bilden soll. Die demnächst veröffentlichte YTM Variante wird allerdings etwas "abgespeckt" sein. Sie wird nur die YTM auf Basis 30/360 beinhalten. Die Implementierung der anderen Zinsberechnungsmethode, wie act/act, act/360 oder act/365 überlasse ich dem interessierten Leser.

Aus den Reaktionen auf meine ersten Beiträgen aus der Reihe "Finanzmathematik" weiß ich, daß es einige Leute gibt, die anscheinend mächtig scharf darauf sind, einen solchen Algorithmus in die Finger zu bekommen. Da ich aber keine Lust habe, sämtliche Arbeit diesen Leuten abzunehmen, werde ich nur das Skelett liefern, das Filet Mignon wird sich dann jeder selber basteln müssen. Ich halte es dennoch für einen äußerst fairen Deal. ;-)

Man sollte auch in der Lage sein, die Beispiel mit der Excel Funktion TAGE360 nachzurechnen. So sollte

=TAGE360(Startdatum;Enddatum;WAHR)

identische Ergebnisse liefern. Ich selber arbeite mit einer finanzmathematischen Formelsammlung und habe meine Ergebnisse mit den Ergebnissen der entsprechenden Formel aus dieser Bibliothek verglichen. Diese Ergebnisse stimmen überein. Und liest man sich die Referenzliste dieses Softwarelieferanten durch, rechnet fast die gesamte Finanzwelt Deutschlands mit diesem Programm. Zu diesem Who-is-who gehören die Deutsche Bundesbank, das Bundesfinanzministerium und nahezu sämtliche Großbanken. Zwar verifiziert dies nicht die Richtigkeit des Algorithmus, aber es ist zumindest tröstlich, das im Falle eines Falles alle gleichermaßen falsch rechnen würden. :-)

Warum diese besondere Betonung auf die Korrektheit der Ergebnisse? Nun, gerade in Excel Communities stößt man häufig auf inkorrekte, falsche und/oder unvollständige Aussagen zu der TAGE360 Formel.

1 Kommentar »

Die effektive jährliche Verzinsung

Posted on Sep 20, 2005 von in SQL Server

Beliebt sind (oder besser gesagt, waren) diese Informationen bei Kreditangeboten aller Art. Einen monatlichen Zinssatz durch die Multiplikation * 12 in einen jährlichen umzurechnen, ist zur gleichen Zeit richtig und doch nicht. Auf diese Weise erhält man nur den Nominalzins. Der sogenannte Zinseszinseffekt kann aber für eine in der Regel weniger erfreuliche Überraschung sorgen. Berücksichtigt man diesen Effekt erhält man den Effektivzins. Dieser liegt umso höher, je mehr Zinszeitpunkte in einer Periode eintreten. Wie man jetzt genau von Nominalzins zum Effektivzins gelangt, ist zu einem guten Teil auch der Kreativität der Mathematiker überlassen. Da gibt es viele verschiedene Methoden, die z.B. mit der exakten Anzahl der Tage rechnen, oder vereinfachend mit 30/360er Regeln und, und... Ferner muß man überlegen, ob und inwieweit Bearbeitungskosten und sonstige Nebenkosten eingerechnet werden oder nicht. All dies interessiert aber hier an dieser Stelle nicht. Wir betrachtet hier einen einfachen Fall.

Beispiel: Die Firma "Wir nehmen's nicht so genau mit der Angabenpflicht unser Kreditangebote GmbH & Co. KG" wirbt mit dem Angebot für nur 1,55% Zinsen pro Monat all die kleinen Konsumwünsche zu erfüllen, auf die man sonst evtl. verzichten müßte. Ferner steht im Angebot eine Angabe zum jährlichen Zins iHv. 18,6%. Da man heutzutage (meint ;-) ) immer mehr repräsentieren zu müssen, um nicht ins gesellschaftliche Abseits, besuchen wir das Büro dieser Firma um einen Kreditvertrag über eine Summe von 10.000 € abzuschließen. Als es dann zur Unterschrift geht, haben wir das Geld zwar schon mental ausgegeben, zum Glück aber nichts an den Augen, als wir über eine Rückzahlungssumme von insgesamt 12.027,05 € in einem Jahr stolpern. Unserer Meinung nach sollte da ein Betrag ihV. 11.860 € stehen. Also über 167 € weniger oder etwas mehr als 1%. Wir verlassen empört das Büro und bauen uns folgendes SQL Statement, um nie wieder auf soetwas herein zufallen.

DECLARE @apr FLOAT 
DECLARE @frequency FLOAT

SELECT @apr = 18.6, @frequency = 12
SELECT 100 * (POWER((1 + ((@apr/100)/@frequency)), @frequency)-1) AS EAR

EAR
-----------------------------------------------------
20.270504548765487

(1 row(s) affected)

Als Input wird der jährliche Nominalzins und die Anzahl der Zinszeitpunkte pro Periode angegeben. Da wir einen monatlichen Zins unterstellen, fallen also 12 Zinszeitpunkte in einem Jahr an. Wie bereits schon oben erwähnt, ist dieses Beispiel sehr einfach und kann beliebig variiert und kompliziert werden. Es sollte aber recht gut den Unterschied zwischen beiden Zinsangaben zeigen.

Speichern von Formeln in Spalten

Posted on Aug 17, 2005 von in SQL Server

Wie könnte es aussehen, wenn man in einem so dynamischen Umfeld arbeitet, daß man selbst die mathematischen Berechnungsformeln nicht hart kodieren will...

Ganze Geschichte »

Kleines Beispiel über COUNT()

Posted on Jul 5, 2005 von in SQL Server

Unter den diversen Aggregatfunktionen des T-SQL Arsenals nimmt COUNT() einen einmaligen Platz ein, weil dies die einzige Funtion ist, die "NULL-aware" ist. Das heißt, je nach Verwendung werden NULL Marker berücksichtigt oder nicht.

Ganze Geschichte »