Created
June 13, 2018 14:26
-
-
Save sarkologist/7e1a223bfb538ba8855da4c407b2138d to your computer and use it in GitHub Desktop.
RSI with composable folds
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import qualified Control.Foldl as Fold | |
import Control.Applicative | |
import Data.Profunctor | |
type Price = Double | |
type Prices = [ Price ] | |
type Period = Int | |
changes :: Prices -> Prices | |
changes ps = zipWith (-) (tail ps) ps | |
avg :: Period -> Fold.Fold Price (Maybe Price) | |
avg period = Fold.Fold step (Left []) (either (const Nothing) Just) | |
where | |
step :: Either Prices Price -> Price -> Either Prices Price | |
step (Left ps) p = | |
let ps' = p : ps | |
in if (period == length ps') | |
then Right (sum ps' / fromIntegral period) | |
else Left ps' | |
step (Right rs) p = | |
let rs' = (rs * (fromIntegral period - 1) + p) / fromIntegral period | |
in Right rs' | |
averageGain = lmap (\x -> if x>0 then x else 0) . avg | |
averageLoss = lmap (\x -> if x<0 then -x else 0) . avg | |
rs = (liftA2.liftA2.liftA2) (/) averageGain averageLoss | |
rsi = (fmap.fmap.fmap) (\rs -> 100 - 100 / (1 + rs)) rs |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment