diff --git a/vnpy/pricing/bsCython/bsCython.pyx b/vnpy/pricing/bsCython/bsCython.pyx index b6c5be1f..5cfff6ab 100644 --- a/vnpy/pricing/bsCython/bsCython.pyx +++ b/vnpy/pricing/bsCython/bsCython.pyx @@ -1,3 +1,5 @@ +from __future__ import division + DX_TARGET = 0.00001 diff --git a/vnpy/pricing/crr.py b/vnpy/pricing/crr.py index 6d70ec52..ca7fabcd 100644 --- a/vnpy/pricing/crr.py +++ b/vnpy/pricing/crr.py @@ -1,5 +1,7 @@ # encoding: UTF-8 +from __future__ import division + ''' Cox-Ross-Rubinstein二叉树期权定价模型,主要用于标的物为期货的美式期权的定价 @@ -54,7 +56,7 @@ def generateTree(f, k, r, t, v, cp, n): p = (a - d) / (u - d) p1 = p / a p2 = (1 - p) / a - + # 计算标的树 uTree[0, 0] = f @@ -139,9 +141,9 @@ def calculateImpv(price, f, k, r, t, cp, n=15): # 检查期权价格是否满足最小价值(即到期行权价值) meet = False - if cp == 1 and (price > f - k): + if cp == 1 and price > (f - k): meet = True - elif cp == -1 and (price > k - f): + elif cp == -1 and price > (k - f): meet = True # 若不满足最小价值,则直接返回0 diff --git a/vnpy/pricing/crrCython.pyd b/vnpy/pricing/crrCython.pyd new file mode 100644 index 00000000..60979cdb Binary files /dev/null and b/vnpy/pricing/crrCython.pyd differ diff --git a/vnpy/pricing/crrCython/crrCython.pyx b/vnpy/pricing/crrCython/crrCython.pyx new file mode 100644 index 00000000..4a96d779 --- /dev/null +++ b/vnpy/pricing/crrCython/crrCython.pyx @@ -0,0 +1,158 @@ +from __future__ import division + +import numpy as np +from math import isnan + +cimport numpy as np +cimport cython + +cdef extern from "math.h" nogil: + double exp(double) + double sqrt(double) + double pow(double, double) + double fmax(double, double) + double fabs(double) + +cdef double STEP_CHANGE = 0.001 +cdef double STEP_UP = 1 + STEP_CHANGE +cdef double STEP_DOWN = 1 - STEP_CHANGE +cdef double STEP_DIFF = STEP_CHANGE * 2 + +cdef double DX_TARGET = 0.00001 + + +#---------------------------------------------------------------------- +cdef tuple generateTree(double f, double k, double r, double t, double v, int cp, int n): + """""" + cdef double dt = t / n + cdef double u = exp(v * sqrt(dt)) + cdef double d = 1.0 / u + cdef double a = 1.0 + + cdef double p = (a - d) / (u - d) + cdef double p1 = p / a + cdef double p2 = (1 - p) / a + + cdef np.ndarray[np.double_t, ndim=2] uTree = np.zeros((n+1, n+1)) + cdef np.ndarray[np.double_t, ndim=2] oTree = np.zeros((n+1, n+1)) + + cdef int i,j + + uTree[0,0] = f + + for i in range(1, n+1): + uTree[0, i] = uTree[0, i-1] * u + for j in range(1, i+1): + uTree[j, i] = uTree[j-1, i-1] * d + + for j in range(n+1): + oTree[j, n] = max(0, cp * (uTree[j, n]-k)) + + for i in range(n-1,-1,-1): + for j in range(i+1): + oTree[j, i] = max((p1 * oTree[j, i+1] + p2 * oTree[j+1, i+1]), + cp * (uTree[j, i] - k)) + + return oTree, uTree + +#---------------------------------------------------------------------- +cpdef double calculatePrice(double f, double k, double r, double t, double v, int cp, int n=15): + """""" + oTree, uTree = generateTree(f, k, r, t, v, cp, n) + return oTree[0, 0] + +#---------------------------------------------------------------------- +cpdef double calculateDelta(double f, double k, double r, double t, double v, int cp, int n=15): + """""" + price1 = calculatePrice(f*STEP_UP, k, r, t, v, cp, n) + price2 = calculatePrice(f*STEP_DOWN, k, r, t, v, cp, n) + delta = (price1 - price2) / (f * STEP_DIFF) + return delta + +#---------------------------------------------------------------------- +cpdef double calculateGamma(double f, double k, double r, double t, double v, int cp, int n=15): + """""" + delta1 = calculateDelta(f*STEP_UP, k, r, t, v, cp, n) + delta2 = calculateDelta(f*STEP_DOWN, k, r, t, v, cp, n) + gamma = (delta1 - delta2) / (f * STEP_DIFF) * pow(f, 2) * 0.0001 + return gamma + +#---------------------------------------------------------------------- +cpdef double calculateTheta(double f, double k, double r, double t, double v, int cp, int n=15): + """""" + price1 = calculatePrice(f, k, r, t*STEP_UP, v, cp, n) + price2 = calculatePrice(f, k, r, t*STEP_DOWN, v, cp, n) + theta = -(price1 - price2) / (t * STEP_DIFF * 240) + return theta + +#---------------------------------------------------------------------- +cpdef double calculateVega(double f, double k, double r, double t, double v, int cp, int n=15): + """""" + vega = calculateOriginalVega(f, k, r, t, v, cp, n) / 100 + return vega + +#---------------------------------------------------------------------- +cdef double calculateOriginalVega(double f, double k, double r, double t, double v, int cp, int n=15): + """""" + price1 = calculatePrice(f, k, r, t, v*STEP_UP, cp, n) + price2 = calculatePrice(f, k, r, t, v*STEP_DOWN, cp, n) + vega = (price1 - price2) / (v * STEP_DIFF) + return vega + +#---------------------------------------------------------------------- +def calculateGreeks(double f, double k, double r, double t, double v, int cp, int n=15): + """""" + cdef double price, delta, gamma, theta, vega + + if v <= 0: + return 0, 0, 0, 0, 0 + + price = calculatePrice(f, k, r, t, v, cp, n) + delta = calculateDelta(f, k, r, t, v, cp, n) + gamma = calculateGamma(f, k, r, t, v, cp, n) + theta = calculateTheta(f, k, r, t, v, cp, n) + vega = calculateVega(f, k, r, t, v, cp, n) + + return price, delta, gamma, theta, vega + +#---------------------------------------------------------------------- +cpdef double calculateImpv(double price, double f, double k, double r, double t, int cp, int n=15): + """""" + cdef double p, v, dx, vega + + if price <= 0: + return 0 + + meet = False + + if cp == 1 and price > (f - k): + meet = True + elif cp == -1 and price > (k - f): + meet = True + + if not meet: + return 0 + + v = 0.3 + + try: + for i in range(50): + p = calculatePrice(f, k, r, t, v, cp, n) + vega = calculateOriginalVega(f, k, r, t, v, cp, n) + + if not vega: + break + + dx = (price - p) / vega + if abs(dx) < DX_TARGET: + break + + v += dx + except: + v = 0 + + if v <= 0: + return 0 + + v = round(v, 4) + return v \ No newline at end of file diff --git a/vnpy/pricing/crrCython/setup.py b/vnpy/pricing/crrCython/setup.py new file mode 100644 index 00000000..982874d7 --- /dev/null +++ b/vnpy/pricing/crrCython/setup.py @@ -0,0 +1,11 @@ +# encoding: UTF-8 +from distutils.core import setup +from Cython.Build import cythonize +import numpy + + +setup( + name = 'crrCython', + ext_modules = cythonize("crrCython.pyx"), + include_dirs = [numpy.get_include()] +) diff --git a/vnpy/trader/app/optionMaster/omEngine.py b/vnpy/trader/app/optionMaster/omEngine.py index 8f9a5e8e..044ac7c0 100644 --- a/vnpy/trader/app/optionMaster/omEngine.py +++ b/vnpy/trader/app/optionMaster/omEngine.py @@ -17,7 +17,7 @@ from vnpy.trader.vtConstant import (PRODUCT_OPTION, OPTION_CALL, OPTION_PUT, DIRECTION_LONG, DIRECTION_SHORT, OFFSET_OPEN, OFFSET_CLOSE, PRICETYPE_LIMITPRICE) -from vnpy.pricing import black, bs, crr, bsCython +from vnpy.pricing import black, bs, crr, bsCython, crrCython from .omBase import (OmOption, OmUnderlying, OmChain, OmPortfolio, EVENT_OM_LOG, EVENT_OM_STRATEGY, EVENT_OM_STRATEGYLOG, @@ -32,6 +32,7 @@ MODEL_DICT['black'] = black MODEL_DICT['bs'] = bs MODEL_DICT['crr'] = crr MODEL_DICT['bsCython'] = bsCython +MODEL_DICT['crrCython'] = crrCython