def test_get_extended_prices(): print("Running test_get_extended_prices()") """ This base method uses the following prioritization to populate the price horizon needed by this local asset: 1. Actual marginal prices offered by the market. 2. Actual marginal prices in prior sequential markets that are similar to the market. 3. Actual marginal prices in prior markets that are being corrected by the market. 4. Modeled prices using the market's price model 5. The market's default price value. 6. Nothing """ # ****************************************************************************************************************** print(" Case 1. Actual marginal prices offered by the market." ) # ***************************************** # The test setup is such that the local asset should use Methods 1 to find an existing marginal price in its market. now = datetime.now() # test_asset = LocalAsset() test_asset_model = LocalAsset() # test_asset = test_asset_model # test_asset_model.object = test_asset test_asset_model.schedulingHorizon = timedelta(hours=0.5) test_market = Market() test_interval = TimeInterval(now, timedelta(hours=1), test_market, now, now) price = 3.14159 test_price = IntervalValue(None, test_interval, test_market, 'test', price) test_market.timeIntervals = [test_interval] test_market.marginalPrices = [test_price] test_mtn = TransactiveNode() test_mtn.markets = [test_market] test_mtn.localAssets = [test_asset_model] assert len(test_market.marginalPrices ) == 1, 'The market was supposed to have a marginal price' assert datetime.now() + test_asset_model.schedulingHorizon \ < test_market.timeIntervals[0].startTime + test_market.intervalDuration, \ 'For this test, the existing marginal price intervals should not extend beyond the scheduling horizon.' try: price_set = test_asset_model.get_extended_prices(test_market) print(" The case ran without errors.") except RuntimeWarning as cause: print(" The case encountered errors.", cause) price_set = [] assert len(price_set) == 1, 'An unexpected number of prices was found' assert price_set[0].value == price, 'The price was no correct' # ****************************************************************************************************************** print( " Case 2. Actual marginal prices in prior sequential market that is similar to the market." ) # **** # The test setup is such that the local asset should sequentially use Methods 1, & 2 to find two marginal prices. now = datetime.now() test_asset_model = LocalAsset() test_asset_model.schedulingHorizon = timedelta( hours=1.5) # Should cause asset to use prior market test_market = Market() test_interval0 = TimeInterval(now, timedelta(hours=1), test_market, now, now) price0 = 3.14159 test_price0 = IntervalValue(None, test_interval0, test_market, 'test', price0) test_market.timeIntervals = [test_interval0] test_market.marginalPrices = [test_price0] test_market.marketSeriesName = "Test Market" test_market.marketClearingTime = now prior_market = Market() test_interval1 = TimeInterval(now, timedelta(hours=1), prior_market, now, now) test_interval2 = TimeInterval(now, timedelta(hours=1), prior_market, now, now + timedelta(hours=1)) price1 = 10 test_price1 = IntervalValue(None, test_interval1, prior_market, 'test', price1) test_price2 = IntervalValue(None, test_interval2, prior_market, 'test', price1) prior_market.timeIntervals = [test_interval1, test_interval2] prior_market.marginalPrices = [test_price1, test_price2] prior_market.marketSeriesName = test_market.marketSeriesName prior_market.marketClearingTime = test_market.marketClearingTime - timedelta( hours=1) test_market.priorMarketInSeries = prior_market # Important pointer to preceding market interval in market series. test_mtn = TransactiveNode() test_mtn.markets = [prior_market, test_market] test_mtn.localAssets = [test_asset_model] assert len(test_market.marginalPrices ) == 1, 'The market was supposed to have a marginal price' assert len(prior_market.marginalPrices ) == 2, "The prior market should have had two prices" assert test_market.marketSeriesName == prior_market.marketSeriesName, 'The market names must be the same' assert test_market.priorMarketInSeries == prior_market, "The market must point to its predecessor in market series" try: price_set = test_asset_model.get_extended_prices(test_market) print(" The case ran without errors.") except RuntimeWarning as result: print(" The case encountered errors.", result) assert len(price_set) == 2, 'An unexpected number of prices was found' assert price_set[0].value == price0, 'The first price was not correct' assert price_set[1].value == price1, 'The second price was not correct' # ****************************************************************************************************************** print( " Case 3. Actual marginal prices in prior markets that are being corrected by the market." ) # ******* # The test setup is such that the local asset should sequentially use Methods 1, 2, & 3 to find three marginal # prices. now = datetime.now() # test_asset = LocalAsset() test_asset_model = LocalAsset() # test_asset.model = test_asset_model # test_asset_model.object = test_asset test_asset_model.schedulingHorizon = timedelta( hours=2.5) # Should cause asset to use prior market test_market = Market() test_interval0 = TimeInterval(now, timedelta(hours=1), test_market, now, now) price0 = 3.14159 test_price0 = IntervalValue(None, test_interval0, test_market, 'test', price0) test_market.timeIntervals = [test_interval0] test_market.marginalPrices = [test_price0] test_market.marketSeriesName = "Test Market" test_market.marketClearingTime = now prior_market = Market() test_interval1 = TimeInterval(now, timedelta(hours=1), prior_market, now, now) test_interval2 = TimeInterval(now, timedelta(hours=1), prior_market, now, now + timedelta(hours=1)) price1 = 10 test_price1 = IntervalValue(None, test_interval1, prior_market, 'test', price1) test_price2 = IntervalValue(None, test_interval2, prior_market, 'test', price1) prior_market.timeIntervals = [test_interval1, test_interval2] prior_market.marginalPrices = [test_price1, test_price2] prior_market.marketSeriesName = test_market.marketSeriesName prior_market.marketClearingTime = test_market.marketClearingTime - timedelta( hours=1) test_market.priorMarketInSeries = prior_market corrected_market = Market() price2 = 20 test_interval3 = TimeInterval(now, timedelta(hours=1), corrected_market, now, now + timedelta(hours=2)) test_price3 = IntervalValue(None, test_interval1, corrected_market, 'test', price2) test_price4 = IntervalValue(None, test_interval2, corrected_market, 'test', price2) test_price5 = IntervalValue(None, test_interval3, corrected_market, 'test', price2) corrected_market.timeIntervals = [ test_interval1, test_interval2, test_interval3 ] corrected_market.marginalPrices = [test_price3, test_price4, test_price5] corrected_market.marketSeriesName = "Corrected Market" corrected_market.marketClearingTime = test_market.marketClearingTime - timedelta( hours=2) corrected_market.intervalDuration = timedelta(hours=1) test_market.priorRefinedMarket = corrected_market test_mtn = TransactiveNode() test_mtn.markets = [corrected_market, prior_market, test_market] test_mtn.localAssets = [test_asset_model] assert len(test_market.marginalPrices ) == 1, 'The market was supposed to have a marginal price' assert len(prior_market.marginalPrices ) == 2, "The prior market should have had two prices" assert len(corrected_market.marginalPrices ) == 3, 'The corrected market should have three prices' assert test_market.marketSeriesName == prior_market.marketSeriesName, 'The market names must be the same' try: price_set = test_asset_model.get_extended_prices(test_market) print(" The case ran without errors.") except RuntimeWarning as result: print(" The case encountered errors.", result) price_set = [] assert len(price_set) == 3, 'An unexpected number of prices was found' assert price_set[0].value == price0, 'The first price was not correct' assert price_set[1].value == price1, 'The second price was not correct' assert price_set[2].value == price2, 'The third price was not correct' # ****************************************************************************************************************** print(" Case 4. Modeled prices using the market's price model." ) # *********************************************** # The test setup is such that the local asset should use Methods 1 & 4 to find four marginal prices. now = datetime.now() test_asset_model = LocalAsset() test_asset_model.schedulingHorizon = timedelta( hours=3.5) # Should cause asset to use prior market test_market = Market() test_interval0 = TimeInterval(now, timedelta(hours=1), test_market, now, now) price0 = 3.14159 test_price0 = IntervalValue(None, test_interval0, test_market, 'test', price0) test_market.timeIntervals = [test_interval0] test_market.marginalPrices = [test_price0] test_market.marketSeriesName = "Test Market" test_market.marketClearingTime = now test_market.priorMarketInSeries = None test_market.priorRefinedMarket = None avg_price = 30 std_price = 0.1 test_market.priceModel = [avg_price, std_price ] * 24 # Critical to this test test_mtn = TransactiveNode() test_mtn.markets = [test_market] test_mtn.localAssets = [test_asset_model] assert len(test_market.marginalPrices ) == 1, 'The market was supposed to have a marginal price' assert len(test_market.priceModel ) == 48, 'A price model must exist for all 2 * 24 hours' try: price_set = test_asset_model.get_extended_prices(test_market) print(" The case ran without errors.") except RuntimeWarning as result: print(" The case encountered errors.", result) price_set = [] # 200207DJH: The assignment of modeled prices now completes the prior successful method to the top of the next hour. # Thereafter, modeled prices are assigned through the top of the hour that exceeds the scheduling # horizon. Therefore, there is some variability in the count of assert len(price_set) == 4 or len(price_set) == 5, \ ('An unexpected number', len(price_set), ' of prices was found') assert price_set[0].value == price0, 'The first price was not correct' assert all([price_set[x].value == avg_price for x in range(1, len(price_set))]), \ 'Prices 1 - 4 were not correct' # ****************************************************************************************************************** print(" Case 5. The market's default price value." ) # ************************************************************ test_asset_model = LocalAsset() test_asset_model.schedulingHorizon = timedelta(hours=4.5) test_market = Market() default_price = 1.2345 test_market.defaultPrice = default_price test_market.priceModel = None test_market.intervalsToClear = 24 test_market.intervalDuration = timedelta(hours=1) test_market.activationLeadTime = timedelta(days=2) test_market.priorRefinedMarket = None test_mtn = TransactiveNode() test_mtn.markets = [test_market] assert type(test_market.defaultPrice ) == float, 'A valid default price must be defined' try: price_set = test_asset_model.get_extended_prices(test_market) print(" The case ran without errors.") except RuntimeWarning: print(" The case encountered errors.") assert len(price_set) == 5, 'The number of horizon prices was unexpected' assert all([price_set[x].value == default_price for x in range(1, len(price_set))]), \ 'The default prices were not used' print("Method test_get_extended_prices() ran to completion.\n")
def test_update_dual_costs(): # TEST_UPDATE_DUAL_COSTS() - test method update_dual_costs() that creates or revises the dual costs in active time # intervals using active vertices, scheduled powers, and marginal prices. # NOTE: This test is virtually identical to the Neighbor test of the same name. print('Running LocalAsset.test_update_dual_costs()') # Create a test Market object. test_market = Market() # Create and store a TimeInterval object. dt = datetime.now( ) # datetime that may be used for most datetime arguments time_interval = TimeInterval(dt, timedelta(hours=1), test_market, dt, dt) test_market.timeIntervals = [time_interval] # Create and store a marginal price IntervalValue object. test_market.marginalPrices = [ IntervalValue(test_market, time_interval, test_market, MeasurementType.MarginalPrice, 0.1) ] # Create a test LocalAsset. test_model = LocalAsset() # Create and store a scheduled power IntervalValue in the active time interval. test_model.scheduledPowers = [ IntervalValue(test_model, time_interval, test_market, MeasurementType.ScheduledPower, 100) ] # Create and store a production cost IntervalValue in the active time interval. test_model.productionCosts = [ IntervalValue(test_model, time_interval, test_market, MeasurementType.ProductionCost, 1000) ] # TEST 1 print('- Test 1: First calculation of a dual cost') try: test_model.update_dual_costs(test_market) print(' The test ran without errors') except RuntimeWarning as cause: print(' The test encountered errors', cause) assert len(test_model.dualCosts ) == 1, 'The wrong number of dual cost values was created' dual_cost = test_model.dualCosts[0].value assert dual_cost == (1000 - 100 * 0.1), 'An unexpected dual cost value was found' # TEST 2 print('- Test 2: Reassignment of an existing dual cost') # Configure the test by modifying the marginal price value. test_market.marginalPrices[0].value = 0.2 try: test_model.update_dual_costs(test_market) print(' The test ran without errors') except RuntimeWarning as cause: print(' The test encountered errors', cause) assert len(test_model.dualCosts ) == 1, 'The wrong number of dual cost values was created' dual_cost = test_model.dualCosts[0].value assert dual_cost == (1000 - 100 * 0.2), 'An unexpected dual cost value was found' # Success. print('Method test_update_dual_costs() ran to completion.\n')