From e7b8c5b8deff16c499795a91bf1f45843e72de1b Mon Sep 17 00:00:00 2001 From: rlskoeser Date: Thu, 4 Jan 2024 15:16:51 -0500 Subject: [PATCH] fine-tune variant distributions per feedback from @LaraBuchak --- simulatingrisk/hawkdovemulti/model.py | 20 ++++++++++++++------ tests/test_hawkdovemulti.py | 8 ++++---- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/simulatingrisk/hawkdovemulti/model.py b/simulatingrisk/hawkdovemulti/model.py index 413c0e5..9b919b0 100644 --- a/simulatingrisk/hawkdovemulti/model.py +++ b/simulatingrisk/hawkdovemulti/model.py @@ -224,9 +224,9 @@ def get_risk_attitude_generator(self): while True: yield self.random.randint(self.min_risk_level, self.max_risk_level) if self.risk_distribution == "normal": - # return values from a normal distribution centered around 4 + # return values from a normal distribution centered around 4.5 while True: - yield int(self.random.gauss(4, 1.5)) + yield round(self.random.gauss(4.5, 1.5)) elif self.risk_distribution == "skewed left": # return values from a triangler distribution centered around 0 while True: @@ -234,23 +234,31 @@ def get_risk_attitude_generator(self): self.random.triangular(self.min_risk_level, self.max_risk_level, 0) ) elif self.risk_distribution == "skewed right": - # return values from a triangler distribution centered around 8 + # return values from a triangular distribution centered around 9 while True: yield round( - self.random.triangular(self.min_risk_level, self.max_risk_level, 8) + self.random.triangular(self.min_risk_level, self.max_risk_level, 9) ) elif self.risk_distribution == "bimodal": # to generate a bimodal distribution, alternately generate # values from two different normal distributions centered # around the beginning and end of our risk attitude range while True: - yield int(self.random.gauss(1, 0.75)) - yield int(self.random.gauss(7, 0.75)) + yield round(self.random.gauss(0, 1.5)) + yield round(self.random.gauss(9, 1.5)) + # NOTE: on smaller grids, using 0/9 makes it extremely + # unlikely to get mid-range risk values (4/5) def get_risk_attitude(self): """return the next value from risk attitude generator, based on configured distribution.""" val = next(self.risk_attitude_generator) + + # for bimodal distribution, clamp values to range + if self.risk_distribution == "bimodal": + return max(self.min_risk_level, min(self.max_risk_level, val)) + + # for all other distributions: # occasionally generators will return values that are out of range. # rather than capping to the min/max and messing up the distribution, # just get the next value diff --git a/tests/test_hawkdovemulti.py b/tests/test_hawkdovemulti.py index 6d3ac80..7638082 100644 --- a/tests/test_hawkdovemulti.py +++ b/tests/test_hawkdovemulti.py @@ -326,7 +326,7 @@ def test_get_risk_attitude_generator(): model.risk_distribution = "normal" model.random.gauss.return_value = 3.3 # value to convert to int next(model.get_risk_attitude_generator()) - model.random.gauss.assert_called_with(4, 1.5) + model.random.gauss.assert_called_with(4.5, 1.5) model.risk_distribution = "skewed left" model.random.triangular.return_value = 2.1 # value to round @@ -339,7 +339,7 @@ def test_get_risk_attitude_generator(): model.random.triangular.return_value = 7.6 # value to round next(model.get_risk_attitude_generator()) model.random.triangular.assert_called_with( - model.min_risk_level, model.max_risk_level, 8 + model.min_risk_level, model.max_risk_level, 9 ) # bimodal returns values from from two different distributions; call twice @@ -348,8 +348,8 @@ def test_get_risk_attitude_generator(): risk_gen = model.get_risk_attitude_generator() next(risk_gen) next(risk_gen) - model.random.gauss.assert_any_call(1, 0.75) - model.random.gauss.assert_any_call(7, 0.75) + model.random.gauss.assert_any_call(0, 1.5) + model.random.gauss.assert_any_call(9, 1.5) def test_get_risk_attitude():