Cython Magic Functions Extension

Loading the extension

IPtyhon has a cythonmagic extension that contains a number of magic functions for working with Cython code. This extension can be loaded using the %load_ext magic as follows:

In [1]:
%load_ext cythonmagic

The %cython_inline magic

The %%cython_inline magic uses Cython.inline to compile a Cython expression. This allows you to enter and run a function body with Cython code. Use a bare return statement to return values.

In [2]:
a = 10
b = 20
In [3]:
%%cython_inline
return a+b
Out[3]:
30

The %cython_pyximport magic

The %%cython_pyximport magic allows you to enter arbitrary Cython code into a cell. That Cython code is written as a .pyx file in the current working directory and then imported using pyximport. You have the specify the name of the module that the Code will appear in. All symbols from the module are imported automatically by the magic function.

In [4]:
%%cython_pyximport foo
def f(x):
    return 4.0*x
In [5]:
f(10)
Out[5]:
40.0

The %cython magic

Probably the most important magic is the %cython magic. This is similar to the %%cython_pyximport magic, but doesn't require you to specify a module name. Instead, the %%cython magic uses manages everything using temporary files in the ~/.cython/magic directory. All of the symbols in the Cython module are imported automatically by the magic.

Here is a simple example of a Black-Scholes options pricing algorithm written in Cython:

In [6]:
%%cython
cimport cython
from libc.math cimport exp, sqrt, pow, log, erf

@cython.cdivision(True)
cdef double std_norm_cdf(double x) nogil:
    return 0.5*(1+erf(x/sqrt(2.0)))

@cython.cdivision(True)
def black_scholes(double s, double k, double t, double v,
                 double rf, double div, double cp):
    """Price an option using the Black-Scholes model.
    
    s : initial stock price
    k : strike price
    t : expiration time
    v : volatility
    rf : risk-free rate
    div : dividend
    cp : +1/-1 for call/put
    """
    cdef double d1, d2, optprice
    with nogil:
        d1 = (log(s/k)+(rf-div+0.5*pow(v,2))*t)/(v*sqrt(t))
        d2 = d1 - v*sqrt(t)
        optprice = cp*s*exp(-div*t)*std_norm_cdf(cp*d1) - \
            cp*k*exp(-rf*t)*std_norm_cdf(cp*d2)
    return optprice
In [7]:
black_scholes(100.0, 100.0, 1.0, 0.3, 0.03, 0.0, -1)
Out[7]:
10.327861752731728
In [8]:
%timeit black_scholes(100.0, 100.0, 1.0, 0.3, 0.03, 0.0, -1)
1000000 loops, best of 3: 821 ns per loop

Cython allows you to specify additional libraries to be linked with your extension, you can do so with the -l flag (also spelled --lib). Note that this flag can be passed more than once to specify multiple libraries, such as -lm -llib2 --lib lib3. Here's a simple example of how to access the system math library:

In [9]:
%%cython -lm
from libc.math cimport sin
print 'sin(1)=', sin(1)
sin(1)= 0.841470984808

You can similarly use the -I/--include flag to add include directories to the search path, and -c/--compile-args to add extra flags that are passed to Cython via the extra_compile_args of the distutils Extension class. Please see the Cython docs on C library usage for more details on the use of these flags.

Back to top