def test_evaluate(): world = {1: True, 2: False, 3: False} credence_history = credence.History([ { 1: .6 }, # credences after first update { 1: .7, 2: .4 }, # credences after second update { 1: .8, 2: .1, 3: .5, 4: .5 }, ]) trading_formulas = { 1: formula.Price( 1, 2 ), # purchase tokens for sentence 1 in quantity equal to the credence for sentence 1 after the second update 2: formula.Price( 2, 3 ), # purchase tokens for sentence 2 in quantity equal to the credence for sentence 2 after the third update } value = inductor.evaluate(trading_formulas, credence_history, world) expected_value = .7 * (1 - .8) + .1 * (0 - .1) assert_equal(value, expected_value)
def trading_algorithm_2(): yield { b: formula.Constant(3.5), b_or_g: formula.Product(formula.Constant(2), formula.Price(if_g_then_r, 2)), } yield { b: formula.Constant(-1), if_g_then_r: formula.Max(formula.Price(b, 1), formula.Price(g, 2)), }
def test_find_credences_trivial(): credence_history = credence.History([]) # empty history trading_formulas = { 1: formula.Price( 1, 1 ), # purchase tokens for sentence 1 in quantity equal to the credence for sentence 1 after the first update } new_credences = inductor.find_credences(trading_formulas, credence_history, 0.5) assert_equal(new_credences[1], 0)
def test_find_credences_multiple(): credence_history = credence.History( []) # empty history; we are on the first update trading_formulas = { # purchase sentence 1 in quantity max(credence-of-sentence-1, credence-of-sentence-2) 1: formula.Max(formula.Price(1, 1), formula.Price(2, 1)), # purchase sentence 2 in quantity 1 - credence-of-sentence-1 - credence-of-sentence-2 2: formula.Sum( formula.Constant(1), formula.Sum( formula.Product(formula.Constant(-1), formula.Price(1, 1)), formula.Product(formula.Constant(-1), formula.Price(2, 1)))) } new_credences = inductor.find_credences(trading_formulas, credence_history, 1e-5) # setting credence[1] to 1 and credence[2] to 0 satisfies the conditions assert_almost_equal(new_credences[1], 1) assert_almost_equal(new_credences[2], 0)
def trade_on_probability(sentence, day, p, slope=10): return formula.Min( formula.Constant(1), formula.Max( formula.Constant(-1), formula.Sum( formula.Constant(slope * p), formula.Product( formula.Constant(-slope), formula.Price(sentence, day) ) ) ) )
def test_find_credences_single(): credence_history = credence.History([]) # empty history trading_formulas = { # purchase sentence 1 in quantity 1 - 3 * credence 1: formula.Sum(formula.Constant(1), formula.Product(formula.Constant(-3), formula.Price(1, 1))), } new_credences = inductor.find_credences(trading_formulas, credence_history, 1e-5) # setting credence to 1/3 yields a trade quantity of zero, which satisfies assert_almost_equal(new_credences[1], 1 / 3)
def compute_budget_factor(budget, observation_history, next_observation, trading_history, next_trading_formulas, credence_history): """ Returns a trading formula representing a weight that can be multiplied with each formula in next_trading_formulas in order to guarantee that the trader's value-of-holdings will not fall below the given budget in any world. The worlds considered are those that are propositionally consistent with the sentences in observation_history and next_observation. The lists observation_history, trading_history, and credence_history all have the same length. next_observation is the most recently observed sentence. next_trading_formulas is a list of (sentence, formula) pairs that will be evaluated on whatever credences the logical inductor outputs when it updates its credences in light of next_observation. We do not get to see these credences when computing the budget factor because the budget factor is an input to the process by which the logical inductor updates its credences. """ assert budget > 0 history_length = len(observation_history) # compute the support for all trading formulas over all days support = union( set(trading_formulas.keys()) for trading_formulas in trading_history) # evaluate the "if" clause in (5.2.1) for i in range(history_length): observations_up_to_i = set(observation_history[:i + 1]) # go over the worlds consistent with the first N observations for world in worlds_consistent_with(observations_up_to_i, support): # calculate the accumulated value of the trader up to update N accumulated_value = 0 for cur_trading_formulas in trading_history[:i + 1]: accumulated_value += evaluate(cur_trading_formulas, credence_history, world) # if we have exceeded our budget on a previous update then we # have no more money to trade now if accumulated_value < -budget + 1e-7: return formula.Constant(0) # create a set of observations up to and including the most recent observations = set(observation_history) observations.add(next_observation) # add atoms for next_trading_formula to the support set support.update(set(next_trading_formulas.keys())) # if we got this far then we have not already exceeded our budget, so now # compute the budget factor budget_divisors = [] for world in worlds_consistent_with(observations, support): # compute our accumulated value in this world accumulated_value = 0 for cur_trading_formulas in trading_history: accumulated_value += evaluate(cur_trading_formulas, credence_history, world) # the money we have left to trade now is our original budget, plus # (resp. minus) any money we made (resp. lost) since the beginning of # time remaining_budget = budget + accumulated_value # this value should be positive given the check that we did above assert remaining_budget > 1e-8 remaining_budget_recip = 1. / remaining_budget # construct a trading formula representing the value of # next_trading_formulas in this world, as a function of the # yet-to-be-determined credences for the latest update value_of_holdings_terms = [] for sentence, trading_formula in next_trading_formulas.items(): # construct a trading formula that looks up the price of tokens for this sentence price = formula.Price(sentence, history_length + 1) # construct a trading formula that computes the value that this # sentence pays out in this world payout = formula.Constant(float(world[sentence])) # construct a trading formula that computes the net value of # purchasing one token of this sentence, which is the payout from the # token minus the price paid to purchase the token value = formula.Sum(payout, formula.Product(formula.Constant(-1), price)) # construct a trading formula that multiplies the number of tokens that we # purchase by their profitability value_of_holdings_terms.append( formula.Product(trading_formula, value)) # construct a trading formula representing the value of the trades # executed on this update in this world value_of_holdings = formula.Sum(*value_of_holdings_terms) # construct a trading formula representing the negation of the above neg_value_of_holdings = formula.Product(formula.Constant(-1), value_of_holdings) # construct a trading formula representing the value we would need to # divide our trades by in this world in order to make sure we do not # exceed our remaining budget divisor_in_this_world = formula.Product( formula.Constant(remaining_budget_recip), neg_value_of_holdings) # add the budget factor for this world to the list of terms budget_divisors.append(divisor_in_this_world) # the final budget divisor is the max of all the possible budget divisors. budget_divisor = formula.Max(*budget_divisors) # now take the safe reciprocal of the divisor, which turns it into a # multiplicative factor and also clips it to 1, so that we only scale # traders down, not up. This is what we want because if a trader is below # its budget then there is no need to scale it up until it uses all of its # remaining budget. budget_factor = formula.SafeReciprocal(budget_divisor) # and we are done! return budget_factor
def trading_algorithm(): for day in enumerator.integers(start=1): yield { digit_n_is_k: make_s_curve(formula.Price(digit_n_is_k, day), .1, 10) }