[Tex/LaTex] How to use Tikz and macros to very efficiently draw recombining binomial trees when taking notes during class

tikz-pgftikz-treestrees

For a class in derivatives pricing I would like to find a way to quickly and efficiently draw recombining binomial trees. The class involved quite a few of those trees and it would be immensely helpful to come up with a way that would allow me to semi-automate the process.

Here's an example (excuse the low resolution; it's the best I've been able to find):
enter image description here

I want to achieve this look by specifying only the number of periods (i.e. horizontal levels); the probability p of going upwards from any node; and the possible values for all nodes. The probabilities p and 1-p should then automatically be displayed above the connecting lines upwards and downwards respectively (as shown in the example). All values for the nodes themselves should be entered manually and their number of course depends on the number of levels.

I am of aware of the possibility of specifying node locations manually in order to achieve the recombining tree but my experience does not suffice to build something to automate this. My question is not about drawing recombining trees in general; it is about finding a way to do it very quickly, as I use LaTeX for my lecture notes.

Best Answer

This calculates the probabilities for a given value of p. You just need to put my binomial=<value> at the start of the tree to select the appropriate style with the appropriate value of p. I've used 0.25 as an example. You also specify the content of the nodes manually, as you requested.

\documentclass[tikz,border=10pt]{standalone}
\usepackage{forest}
\tikzset{
  my label/.style={font=\small},
  my edge label/.style={font=\scriptsize, midway, sloped},
}
\forestset{
  my binomial/.style={
    TeX={\def\p{#1}},
    for tree={
      grow'=0,
      parent anchor=east,
      child anchor=west,
      circle,
      fill,
      text width=2.5pt,
      inner sep=0pt,
      outer sep=0pt,
      edge={->},
      s sep+=5pt,
      l sep+=25pt,
      before typesetting nodes={
        if level=0{
          label/.wrap pgfmath arg={[my label]left:##1}{content()},
          content={1},
        }{
          if n children=0{
            label/.wrap pgfmath arg={[my label]right:##1}{content()},
          }{
            if n=1{
              label/.wrap pgfmath arg={[my label]above:##1}{content()},
            }{
              label/.wrap pgfmath arg={[my label]below:##1}{content()},
            },
          },
          if n=1{
            content/.wrap pgfmath arg={##1}{content("!u")*\p},
            edge label/.wrap pgfmath arg={{node [my edge label, above] {##1}}}{content("!u")*\p}
          }{
            content/.wrap pgfmath arg={##1}{content("!u")*(1-\p)},
            edge label/.wrap pgfmath arg={{node [my edge label, below] {##1}}}{content("!u")*(1-\p)}
          },
        },
        delay={
          content={},
        },
      },
    }
  }
}
\begin{document}
  \begin{forest}
    my binomial=.25
    [A
      [B
        [D
          [H]
          [I]
        ]
        [E
          [J]
          [K]
        ]
      ]
      [C
        [F
          [L]
          [M]
        ]
        [G
          [N]
          [O]
        ]
      ]
    ]
  \end{forest}
\end{document}

binomial tree

EDIT

Figured out how to turn this into a proper style thanks to Sašo Živanović.

Related Question