Skip to content

Commit

Permalink
Removed unused 'Underling' element.
Browse files Browse the repository at this point in the history
  • Loading branch information
johnbywater committed Oct 17, 2017
1 parent a3b7d67 commit 8a3636c
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 78 deletions.
40 changes: 19 additions & 21 deletions quantdsl/priceprocess/blackscholes.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,35 +54,34 @@ def get_brownian_motions(self, observation_date, requirements, path_count, calib
commodity_names, fixing_dates = self.get_commodity_names_and_fixing_dates(observation_date, requirements)

len_commodity_names = len(commodity_names)
if len_commodity_names == 0:
return []

len_fixing_dates = len(fixing_dates)
if len_fixing_dates == 0:
return []

# Check the observation date equals the first fixing date.
assert observation_date == fixing_dates[0], "Observation date {} not equal to first fixing date: {}" \
"".format(observation_date, fixing_dates[0])

# Diffuse random variables through each date for each market (uncorrelated increments).
brownian_motions = scipy.zeros((len_commodity_names, len_fixing_dates, path_count))
for i in range(len_commodity_names):
_start_date = fixing_dates[0]
start_rv = brownian_motions[i][0]
for j in range(len_fixing_dates - 1):
fixing_date = fixing_dates[j + 1]
draws = scipy.random.standard_normal(path_count)
T = get_duration_years(_start_date, fixing_date)
if T < 0:
raise DslError("Can't really square root negative time durations: %s. Contract starts before observation time?" % T)
end_rv = start_rv + scipy.sqrt(T) * draws
try:
brownian_motions[i][j + 1] = end_rv
except ValueError as e:
raise ValueError("Can't set end_rv in brownian_motions: %s" % e)
_start_date = fixing_date
start_rv = end_rv
all_brownian_motions = []

if len_fixing_dates and len_commodity_names:
for i in range(len_commodity_names):
_start_date = fixing_dates[0]
start_rv = brownian_motions[i][0]
for j in range(len_fixing_dates - 1):
fixing_date = fixing_dates[j + 1]
draws = scipy.random.standard_normal(path_count)
T = get_duration_years(_start_date, fixing_date)
if T < 0:
raise DslError("Can't really square root negative time durations: %s. Contract starts before observation time?" % T)
end_rv = start_rv + scipy.sqrt(T) * draws
try:
brownian_motions[i][j + 1] = end_rv
except ValueError as e:
raise ValueError("Can't set end_rv in brownian_motions: %s" % e)
_start_date = fixing_date
start_rv = end_rv

if len_commodity_names > 1:
correlation_matrix = scipy.zeros((len_commodity_names, len_commodity_names))
Expand Down Expand Up @@ -124,7 +123,6 @@ def get_brownian_motions(self, observation_date, requirements, path_count, calib
brownian_motions = brownian_motions_correlated

# Put random variables into a nested Python dict, keyed by market commodity_name and fixing date.
all_brownian_motions = []
for i, commodity_name in enumerate(commodity_names):
market_rvs = []
for j, fixing_date in enumerate(fixing_dates):
Expand Down
78 changes: 31 additions & 47 deletions quantdsl/semantics.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,13 @@ def pprint(self, indent=''):
for i, arg in enumerate(self._args):
if lenArgs > 1:
msg += indent
if isinstance(arg, DslObject):
msg += arg.pprint(indent)
else:
msg += str(arg)
# if isinstance(arg, DslObject):
# msg += arg.pprint(indent)
# else:
# msg += str(arg)
assert isinstance(arg, DslObject), type(arg)
msg += arg.pprint(indent)

if i < lenArgs - 1:
msg += ","
if lenArgs > 1:
Expand Down Expand Up @@ -97,9 +100,9 @@ def hash_single_arg(self, _arg):
_hash = str(hash(_arg))
return _hash

def __hash__(self):
return self.hash

# def __hash__(self):
# return self.hash
#
@abstractmethod
def validate(self, args):
"""
Expand Down Expand Up @@ -140,11 +143,8 @@ def assert_args_arg(self, args, posn, required_type):

elif not isinstance(args[posn], required_type):
if isinstance(required_type, (list, tuple)):
try:
required_type_names = [i.__name__ for i in required_type]
required_type_names = ", ".join(required_type_names)
except AttributeError as e:
raise AttributeError(required_type)
required_type_names = [i.__name__ for i in required_type]
required_type_names = ", ".join(required_type_names)
else:
required_type_names = required_type.__name__
desc = "argument %s must be %s" % (posn, required_type_names)
Expand Down Expand Up @@ -428,8 +428,8 @@ def makeStr(dsl_expr):

def validate(self, args):
self.assert_args_len(args, required_len=2)
self.assert_args_arg(args, posn=0, required_type=(DslExpression, Date, TimeDelta, Underlying))
self.assert_args_arg(args, posn=1, required_type=(DslExpression, Date, TimeDelta, Underlying))
self.assert_args_arg(args, posn=0, required_type=(DslExpression, Date, TimeDelta))
self.assert_args_arg(args, posn=1, required_type=(DslExpression, Date, TimeDelta))

@property
def left(self):
Expand All @@ -443,10 +443,11 @@ def evaluate(self, **kwds):
left = self.left.evaluate(**kwds)
right = self.right.evaluate(**kwds)
try:
if self.op_code in NUMEXPR_OPS and (isinstance(left, ndarray) or isinstance(right, ndarray)):
return self.op_numexpr(left, right)
else:
return self.op_python(left, right)
# if self.op_code in NUMEXPR_OPS and (isinstance(left, ndarray) or isinstance(right, ndarray)):
# return self.op_numexpr(left, right)
# else:
# return self.op_python(left, right)
return self.op_python(left, right)
except TypeError as e:
raise DslBinOpArgsError("unable to %s" % self.__class__.__name__.lower(),
"%s and %s: %s" % (self.left, self.right, e),
Expand All @@ -458,15 +459,15 @@ def op_python(self, left, right):
Returns result of operating on two args.
"""

def op_numexpr(self, left, right):
# return left ** right
expr = 'left {} right'.format(self.op_code)
try:
return numexpr.evaluate(expr)
except SyntaxError as e:
raise SyntaxError("Invalid numexpr syntax in class: {}: '{}'".format(
self.__class__.__name__, expr
))
# def op_numexpr(self, left, right):
# # return left ** right
# expr = 'left {} right'.format(self.op_code)
# try:
# return numexpr.evaluate(expr)
# except SyntaxError as e:
# raise SyntaxError("Invalid numexpr syntax in class: {}: '{}'".format(
# self.__class__.__name__, expr
# ))


class Add(BinOp):
Expand Down Expand Up @@ -511,8 +512,8 @@ def op_python(self, left, right):

def validate(self, args):
self.assert_args_len(args, required_len=2)
self.assert_args_arg(args, posn=0, required_type=(DslExpression, Date, TimeDelta, Underlying))
self.assert_args_arg(args, posn=1, required_type=(DslExpression, Date, TimeDelta, Underlying))
self.assert_args_arg(args, posn=0, required_type=(DslExpression, Date, TimeDelta))
self.assert_args_arg(args, posn=1, required_type=(DslExpression, Date, TimeDelta))


class Mod(BinOp):
Expand Down Expand Up @@ -633,19 +634,6 @@ def pprint(self, indent=''):
return "Stub('%s')" % self.name


# Todo: Drop this.
class Underlying(DslObject):
def validate(self, args):
self.assert_args_len(args, 1)

@property
def expr(self):
return self._args[0]

def evaluate(self, **_):
return self.expr


class FunctionDef(DslObject):
"""
A DSL function def creates DSL expressions when called. They can be defined as
Expand Down Expand Up @@ -904,10 +892,7 @@ def call_functions(self, present_time=None, observation_date=None, pending_call_
if isinstance(call_arg_expr, DslExpression):
# Substitute names, etc.
# Decide whether to evaluate, or just pass the expression into the function call.
if isinstance(call_arg_expr, Underlying):
# It's explicitly wrapped as an "underlying", so unwrap it as expected.
call_arg_value = call_arg_expr.evaluate()
elif isinstance(call_arg_expr, FunctionCall):
if isinstance(call_arg_expr, FunctionCall):
# It's a function call, so try to call it (attempt to simplify things going forward).
# - can't do it with stack, because we don't want to stack calls with wrong effective present time
# - can't just do it without stack, because recursive functions risk recursion depth exception
Expand Down Expand Up @@ -1244,7 +1229,6 @@ def get_date(self, **kwargs):
'Sub': Sub,
'TimeDelta': TimeDelta,
'UnarySub': UnarySub,
'Underlying': Underlying,
}


Expand Down
9 changes: 0 additions & 9 deletions quantdsl/tests/_____test.py
Original file line number Diff line number Diff line change
Expand Up @@ -379,15 +379,6 @@ def testValuation(self):
# self.assertValuation(specification, 20.0, 2.0, 0.07, 0.06, 0.2, 0.2)
#
#
# class TestDslFunctionDefOption(DslTestCase):
#
# def testValuation(self):
# specification = """
# def Option(date, strike, x, y):
# return Wait(date, Choice(x - strike, y))
# Option(Date('2012-01-01'), 9, Underlying(Market('#1')), 0)
# """
# self.assertValuation(specification, 2.356, 0.660, 0.068, 0.04, 0.2, 0.2)


# class TestDslFunctionDefEuropean(DslTestCase):
Expand Down
15 changes: 14 additions & 1 deletion quantdsl/tests/test_semantics.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from mock import Mock
from scipy import array

from quantdsl.exceptions import DslNameError, DslSyntaxError, DslSystemError
from quantdsl.exceptions import DslNameError, DslSyntaxError, DslSystemError, DslPresentTimeNotInScope
from quantdsl.semantics import Add, And, Date, Div, DslNamespace, DslObject, Max, Min, Mult, Name, Number, Or, \
String, Sub, TimeDelta, Pow, FunctionDef, FunctionCall, Stub, FunctionArg

Expand Down Expand Up @@ -48,6 +48,16 @@ def test_str(self):
self.assertEqual(str(self.obj), "Subclass()")
self.assertEqual(str(Subclass(Subclass())), "Subclass(Subclass())")

def test_get_present_time(self):
# Check method returns given value.
present_time = self.obj.get_present_time({'present_time': datetime.datetime(2011, 1, 1)})
self.assertEqual(present_time, datetime.datetime(2011, 1, 1))

# Check method raises exception when value not in scope.
with self.assertRaises(DslPresentTimeNotInScope):
self.obj.get_present_time({})



class TestString(TestCase):
def test_value(self):
Expand Down Expand Up @@ -244,6 +254,9 @@ def test_evaluate(self):
with self.assertRaises(DslSyntaxError):
obj.evaluate()

obj = Sub(Date('2011-1-2'), Date('2011-1-1'))
self.assertEqual(obj.evaluate(), relativedelta(days=1))


class TestMul(TestCase):
def test_evaluate(self):
Expand Down

0 comments on commit 8a3636c

Please sign in to comment.