;lib: pricesAtDate: refactor
This commit is contained in:
		
							parent
							
								
									c14f22b975
								
							
						
					
					
						commit
						7177f533b2
					
				| @ -99,53 +99,6 @@ amountValueAtDate pricedirectives styles mto d a = | |||||||
|       styleAmount styles |       styleAmount styles | ||||||
|       amount{acommodity=comm, aquantity=rate * aquantity a} |       amount{acommodity=comm, aquantity=rate * aquantity a} | ||||||
| 
 | 
 | ||||||
| ------------------------------------------------------------------------------ |  | ||||||
| -- Building a price graph |  | ||||||
| 
 |  | ||||||
| -- | Convert a list of market price directives in parse order to a |  | ||||||
| -- graph of all prices in effect on a given day, allowing efficient |  | ||||||
| -- lookup of exchange rates between commodity pairs. |  | ||||||
| pricesAtDate :: [PriceDirective] -> Day -> PriceGraph |  | ||||||
| pricesAtDate pricedirectives d = PriceGraph{prGraph=g, prNodemap=m, prDeclaredPairs=dps} |  | ||||||
|   where |  | ||||||
|     -- build the graph and associated node map |  | ||||||
|     (g :: Gr CommoditySymbol Quantity, m :: NodeMap CommoditySymbol) = |  | ||||||
|       mkMapGraph |  | ||||||
|       (dbg5 "g nodelabels" $ sort allcomms) -- this must include all nodes mentioned in edges |  | ||||||
|       (dbg5 "g edges"      $ [(mpfrom, mpto, mprate) | MarketPrice{..} <- prices]) |  | ||||||
|       where |  | ||||||
|         prices   = declaredprices ++ reverseprices |  | ||||||
|         allcomms = map mpfrom prices |  | ||||||
| 
 |  | ||||||
|     -- get the latest (on or before date d) declared price for each commodity pair |  | ||||||
|     declaredprices :: [MarketPrice] = |  | ||||||
|       dbg5 "declaredprices" $ |  | ||||||
|       nubSortBy (compare `on` (\(MarketPrice{..})->(mpfrom,mpto))) $  -- keep only the first (ie newest and latest parsed) price for each pair |  | ||||||
|       map snd $  -- discard the parse order label |  | ||||||
|       sortBy (flip compare `on` (\(parseorder,mp)->(mpdate mp,parseorder))) $  -- sort with newest dates and latest parse order first |  | ||||||
|       zip [1..] $  -- label with parse order |  | ||||||
|       map priceDirectiveToMarketPrice $ |  | ||||||
|       filter ((<=d).pddate) pricedirectives  -- consider only price declarations up to the valuation date |  | ||||||
| 
 |  | ||||||
|     -- infer additional reverse prices where not already declared |  | ||||||
|     reverseprices = |  | ||||||
|       dbg5 "reverseprices" $ |  | ||||||
|       map marketPriceReverse declaredprices \\ declaredprices |  | ||||||
| 
 |  | ||||||
|     -- remember which edges correspond to declared prices |  | ||||||
|     dps = [(node m mpfrom, node m mpto) | MarketPrice{..} <- declaredprices ] |  | ||||||
| 
 |  | ||||||
| priceDirectiveToMarketPrice :: PriceDirective -> MarketPrice |  | ||||||
| priceDirectiveToMarketPrice PriceDirective{..} = |  | ||||||
|   MarketPrice{ mpdate = pddate |  | ||||||
|              , mpfrom = pdcommodity |  | ||||||
|              , mpto   = acommodity pdamount |  | ||||||
|              , mprate = aquantity pdamount |  | ||||||
|              } |  | ||||||
| 
 |  | ||||||
| marketPriceReverse :: MarketPrice -> MarketPrice |  | ||||||
| marketPriceReverse mp@MarketPrice{..} = mp{mpfrom=mpto, mpto=mpfrom, mprate=1/mprate} |  | ||||||
| 
 |  | ||||||
| ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | ||||||
| -- Market price lookup | -- Market price lookup | ||||||
| 
 | 
 | ||||||
| @ -242,6 +195,60 @@ priceLookup pricedirectives d from mto = | |||||||
|           -- log a message and a Maybe Quantity, hiding Just/Nothing and limiting decimal places |           -- log a message and a Maybe Quantity, hiding Just/Nothing and limiting decimal places | ||||||
|           dbg msg = dbg4With (((msg++": ")++) . maybe "" (show . roundTo 8)) |           dbg msg = dbg4With (((msg++": ")++) . maybe "" (show . roundTo 8)) | ||||||
| 
 | 
 | ||||||
|  | ------------------------------------------------------------------------------ | ||||||
|  | -- Building the price graph (network of commodity conversions) on a given day. | ||||||
|  | 
 | ||||||
|  | -- | Convert a list of market price directives in parse order to a | ||||||
|  | -- graph of all prices in effect on a given day, allowing efficient | ||||||
|  | -- lookup of exchange rates between commodity pairs. | ||||||
|  | pricesAtDate :: [PriceDirective] -> Day -> PriceGraph | ||||||
|  | pricesAtDate pricedirectives d = PriceGraph{prGraph=g, prNodemap=m, prDeclaredPairs=dps} | ||||||
|  |   where | ||||||
|  |     declaredprices = latestPriceForEachPairOn pricedirectives d | ||||||
|  | 
 | ||||||
|  |     -- infer additional reverse prices where not already declared | ||||||
|  |     reverseprices = | ||||||
|  |       dbg5 "reverseprices" $ | ||||||
|  |       map marketPriceReverse declaredprices \\ declaredprices | ||||||
|  | 
 | ||||||
|  |     -- build the graph and associated node map | ||||||
|  |     -- (g :: Gr CommoditySymbol Quantity, m :: NodeMap CommoditySymbol) = | ||||||
|  |     (g, m) = | ||||||
|  |       mkMapGraph | ||||||
|  |       (dbg5 "g nodelabels" $ sort allcomms) -- this must include all nodes mentioned in edges | ||||||
|  |       (dbg5 "g edges"      $ [(mpfrom, mpto, mprate) | MarketPrice{..} <- prices]) | ||||||
|  |       :: (Gr CommoditySymbol Quantity, NodeMap CommoditySymbol) | ||||||
|  |       where | ||||||
|  |         prices   = declaredprices ++ reverseprices | ||||||
|  |         allcomms = map mpfrom prices | ||||||
|  | 
 | ||||||
|  |     -- remember which edges correspond to declared prices | ||||||
|  |     dps = [(node m mpfrom, node m mpto) | MarketPrice{..} <- declaredprices ] | ||||||
|  | 
 | ||||||
|  | -- From a list of price directives in parse order, get the latest | ||||||
|  | -- price declared on or before date d for each commodity pair. | ||||||
|  | latestPriceForEachPairOn :: [PriceDirective] -> Day -> [MarketPrice] | ||||||
|  | latestPriceForEachPairOn pricedirectives d = | ||||||
|  |   dbg5 "latestPriceForEachPairOn" $ | ||||||
|  |   nubSortBy (compare `on` (\(MarketPrice{..})->(mpfrom,mpto))) $  -- keep only the first (ie newest and latest parsed) price for each pair | ||||||
|  |   map snd $  -- discard the parse order label | ||||||
|  |   sortBy (flip compare `on` (\(parseorder,mp)->(mpdate mp,parseorder))) $  -- sort with newest dates and latest parse order first | ||||||
|  |   zip [1..] $  -- label with parse order | ||||||
|  |   map priceDirectiveToMarketPrice $ | ||||||
|  |   filter ((<=d).pddate) pricedirectives  -- consider only price declarations up to the valuation date | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | priceDirectiveToMarketPrice :: PriceDirective -> MarketPrice | ||||||
|  | priceDirectiveToMarketPrice PriceDirective{..} = | ||||||
|  |   MarketPrice{ mpdate = pddate | ||||||
|  |              , mpfrom = pdcommodity | ||||||
|  |              , mpto   = acommodity pdamount | ||||||
|  |              , mprate = aquantity pdamount | ||||||
|  |              } | ||||||
|  | 
 | ||||||
|  | marketPriceReverse :: MarketPrice -> MarketPrice | ||||||
|  | marketPriceReverse mp@MarketPrice{..} = mp{mpfrom=mpto, mpto=mpfrom, mprate=1/mprate} | ||||||
|  | 
 | ||||||
| ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | ||||||
| -- fgl helpers | -- fgl helpers | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user