--- /dev/null
+John Benediktsson
--- /dev/null
+! Copyright (C) 2008 John Benediktsson
+! See http://factorcode.org/license.txt for BSD license
+
+USING: help.markup help.syntax ;
+
+IN: math.compare
+
+HELP: absmin
+{ $values { "a" "a number" } { "b" "a number" } { "x" "a number" } }
+{ $description
+ "Returns the smaller absolute number with the original sign."
+} ;
+
+HELP: absmax
+{ $values { "a" "a number" } { "b" "a number" } { "x" "a number" } }
+{ $description
+ "Returns the larger absolute number with the original sign."
+} ;
+
+HELP: posmax
+{ $values { "a" "a number" } { "b" "a number" } { "x" "a number" } }
+{ $description
+ "Returns the most-positive value, or zero if both are negative."
+} ;
+
+HELP: negmin
+{ $values { "a" "a number" } { "b" "a number" } { "x" "a number" } }
+{ $description
+ "Returns the most-negative value, or zero if both are positive."
+} ;
+
+HELP: clamp
+{ $values { "a" "a number" } { "value" "a number" } { "b" "a number" } { "x" "a number" } }
+{ $description
+ "Returns the value when between 'a' and 'b', 'a' if <= 'a', or 'b' if >= 'b'."
+} ;
+
--- /dev/null
+! Copyright (C) 2008 John Benediktsson
+! See http://factorcode.org/license.txt for BSD license
+
+USING: kernel math math.functions math.compare tools.test ;
+
+IN: math.compare.tests
+
+[ -1 ] [ -1 5 absmin ] unit-test
+[ -1 ] [ -1 -5 absmin ] unit-test
+
+[ -5 ] [ 1 -5 absmax ] unit-test
+[ 5 ] [ 1 5 absmax ] unit-test
+
+[ 0 ] [ -1 -3 posmax ] unit-test
+[ 1 ] [ 1 -3 posmax ] unit-test
+[ 3 ] [ -1 3 posmax ] unit-test
+
+[ 0 ] [ 1 3 negmin ] unit-test
+[ -3 ] [ 1 -3 negmin ] unit-test
+[ -1 ] [ -1 3 negmin ] unit-test
+
+[ 0 ] [ 0 -1 2 clamp ] unit-test
+[ 1 ] [ 0 1 2 clamp ] unit-test
+[ 2 ] [ 0 3 2 clamp ] unit-test
+
+
+
+
--- /dev/null
+! Copyright (C) 2008 John Benediktsson
+! See http://factorcode.org/license.txt for BSD license
+
+USING: math math.order kernel ;
+
+IN: math.compare
+
+: absmin ( a b -- x )
+ [ [ abs ] bi@ < ] 2keep ? ;
+
+: absmax ( a b -- x )
+ [ [ abs ] bi@ > ] 2keep ? ;
+
+: posmax ( a b -- x )
+ 0 max max ;
+
+: negmin ( a b -- x )
+ 0 min min ;
+
+: clamp ( a value b -- x )
+ min max ;
+
--- /dev/null
+Comparison functions.
--- /dev/null
+John Benediktsson
--- /dev/null
+! Copyright (C) 2008 John Benediktsson
+! See http://factorcode.org/license.txt for BSD license
+
+USING: help.markup help.syntax ;
+
+IN: math.finance
+
+HELP: enumerate
+{ $values { "seq" "a sequence" } { "newseq" "a sequence" } }
+{ $description "Returns a new sequence where each element is an array of { value, index }" } ;
+
+HELP: distribute
+{ $values { "amount" "a number of amount" } { "n" "a number of buckets" } { "seq" "a sequence" } }
+{ $description
+ "Distribute 'amount' in 'n' buckets, as equally as possible. Returns a list of 'n' elements that sum to 'amount'.\n"
+}
+{ $examples
+ { $example
+ "USING: math.finance"
+ "3 1 distribute"
+ "{ 3 }" }
+ { $example
+ "USING: math.finance"
+ "3 3 distribute"
+ "{ 1 1 1 }" }
+ { $example
+ "USING: math.finance"
+ "5 3 distribute"
+ "{ 2 1 2 }" }
+ { $example
+ "USING: math.finance"
+ "3 5 distribute"
+ "{ 1 0 1 0 1 }" }
+ { $example
+ "USING: math.finance"
+ "1000 7 distribute"
+ "{ 143 143 143 142 143 143 143 }" }
+} ;
+
+HELP: sma
+{ $values { "seq" "a sequence" } { "n" "number of periods" } { "newseq" "a sequence" } }
+{ $description "Returns the Simple Moving Average with the specified periodicity." } ;
+
+HELP: ema
+{ $values { "seq" "a sequence" } { "n" "number of periods" } { "newseq" "a sequence" } }
+{ $description
+ "Returns the Exponential Moving Average with the specified periodicity, calculated by:\n"
+ { $list
+ "A = 2.0 / (N + 1)"
+ "EMA[t] = (A * SEQ[t]) + ((1-A) * EMA[t-1])" }
+} ;
+
+HELP: macd
+{ $values { "seq" "a sequence" } { "n1" "short number of periods" } { "n2" "long number of periods" } { "newseq" "a sequence" } }
+{ $description
+ "Returns the Moving Average Converge of the sequence, calculated by:\n"
+ { $list "MACD[t] = EMA2[t] - EMA1[t]" }
+} ;
+
+HELP: momentum
+{ $values { "seq" "a sequence" } { "n" "number of periods" } { "newseq" "a sequence" } }
+{ $description
+ "Returns the Momentum of the sequence, calculated by:\n"
+ { $list "MOM[t] = SEQ[t] - SEQ[t-n]" }
+} ;
+
--- /dev/null
+USING: kernel math math.functions math.finance tools.test ;
+
+IN: math.finance.tests
+
+[ { 2 4 } ] [ { 1 3 5 } 2 sma ] unit-test
+
+[ { 1 3 1 } ] [ { 1 3 2 6 3 } 2 momentum ] unit-test
+
+[ { 3 } ] [ 3 1 distribute ] unit-test
+[ { 1 1 1 } ] [ 3 3 distribute ] unit-test
+[ { 2 1 2 } ] [ 5 3 distribute ] unit-test
+[ { 1 0 1 0 1 } ] [ 3 5 distribute ] unit-test
+[ { 143 143 143 142 143 143 143 } ] [ 1000 7 distribute ] unit-test
+
--- /dev/null
+! Copyright (C) 2008 John Benediktsson
+! See http://factorcode.org/license.txt for BSD license
+
+USING: arrays assocs kernel grouping sequences shuffle
+math math.functions math.statistics math.vectors ;
+
+IN: math.finance
+
+: enumerate ( seq -- newseq )
+ <enum> >alist ;
+
+: distribute ( amount n -- seq )
+ [ / ] keep 0 <array> [ 0 0 ] dip
+ [ + [ [ dup ] dip + ] dip
+ [ dup round ] dip 2dup -
+ [ drop ] dip ] map 3nip ;
+
+<PRIVATE
+
+: weighted ( x y a -- z )
+ tuck [ * ] [ 1 swap - * ] 2bi* + ;
+
+: a ( n -- a )
+ 1 + 2 swap / ;
+
+: first-rest ( seq -- first rest )
+ [ first ] keep 1 tail-slice ;
+
+PRIVATE>
+
+: ema ( seq n -- newseq )
+ a swap first-rest swap [ [ dup ] 2dip swap rot weighted ] accumulate 2nip ;
+
+: sma ( seq n -- newseq )
+ clump [ mean ] map ;
+
+: macd ( seq n1 n2 -- newseq )
+ rot dup ema [ swap ema ] dip v- ;
+
+: momentum ( seq n -- newseq )
+ 2dup tail-slice -rot swap [ length ] keep
+ [ - neg ] dip swap head-slice v- ;
+
--- /dev/null
+Moving averages and other calculations useful for finance.
-\r
-USING: help.syntax help.markup kernel prettyprint sequences strings ;\r
-\r
-IN: printf\r
-\r
-HELP: printf\r
-{ $values { "format-string" string } }\r
-{ $description "Writes the arguments (specified on the stack) formatted according to the format string." } \r
-{ $examples \r
- { $example\r
- "USING: printf ;"\r
- "123 \"%05d\" printf"\r
- "00123" }\r
- { $example\r
- "USING: printf ;"\r
- "HEX: ff \"%04X\" printf"\r
- "00FF" }\r
- { $example\r
- "USING: printf ;"\r
- "1.23456789 \"%.3f\" printf"\r
- "1.234" }\r
- { $example \r
- "USING: printf ;"\r
- "1234567890 \"%.5e\" printf"\r
- "1.23456e+09" }\r
- { $example\r
- "USING: printf ;"\r
- "12 \"%'#4d\" printf"\r
- "##12" }\r
- { $example\r
- "USING: printf ;"\r
- "1234 \"%+d\" printf"\r
- "+1234" }\r
-} ;\r
-\r
-HELP: sprintf\r
-{ $values { "format-string" string } { "result" string } }\r
-{ $description "Returns the arguments (specified on the stack) formatted according to the format string as a result string." } \r
-{ $see-also printf } ;\r
-\r
-ARTICLE: "printf" "Formatted printing"\r
-"The " { $link printf } " and " { $link sprintf } " words are used for formatted printing.\n"\r
-"\n"\r
-"Several format specifications exist for handling arguments of different types, and specifying attributes for the result string, including such things as maximum width, padding, and decimals.\n"\r
-{ $table\r
- { "%%" "Single %" "" }\r
- { "%P.Ds" "String format" "string" }\r
- { "%P.DS" "String format uppercase" "string" }\r
- { "%c" "Character format" "char" } \r
- { "%C" "Character format uppercase" "char" } \r
- { "%+Pd" "Integer format" "fixnum" }\r
- { "%+P.De" "Scientific notation" "fixnum, float" }\r
- { "%+P.DE" "Scientific notation" "fixnum, float" }\r
- { "%+P.Df" "Fixed format" "fixnum, float" }\r
- { "%+Px" "Hexadecimal" "hex" }\r
- { "%+PX" "Hexadecimal uppercase" "hex" }\r
-}\r
-"\n"\r
-"A plus sign ('+') is used to optionally specify that the number should be formatted with a '+' preceeding it if positive.\n"\r
-"\n"\r
-"Padding ('P') is used to optionally specify the minimum width of the result string, the padding character, and the alignment. By default, the padding character defaults to a space and the alignment defaults to right-aligned. For example:\n"\r
-{ $list\r
- "\"%5s\" formats a string padding with spaces up to 5 characters wide."\r
- "\"%08d\" formats an integer padding with zeros up to 3 characters wide."\r
- "\"%'#5f\" formats a float padding with '#' up to 3 characters wide."\r
- "\"%-10d\" formats an integer to 10 characters wide and left-aligns." \r
-}\r
-"\n"\r
-"Digits ('D') is used to optionally specify the maximum digits in the result string. For example:\n"\r
-{ $list \r
- "\"%.3s\" formats a string to truncate at 3 characters (from the left)."\r
- "\"%.10f\" formats a float to pad-right with zeros up to 10 digits beyond the decimal point."\r
- "\"%.5E\" formats a float into scientific notation with zeros up to 5 digits beyond the decimal point, but before the exponent."\r
-} ;\r
+
+USING: help.syntax help.markup kernel prettyprint sequences strings ;
+
+IN: printf
+
+HELP: printf
+{ $values { "format-string" string } }
+{ $description "Writes the arguments (specified on the stack) formatted according to the format string." }
+{ $examples
+ { $example
+ "USING: printf ;"
+ "123 \"%05d\" printf"
+ "00123" }
+ { $example
+ "USING: printf ;"
+ "HEX: ff \"%04X\" printf"
+ "00FF" }
+ { $example
+ "USING: printf ;"
+ "1.23456789 \"%.3f\" printf"
+ "1.234" }
+ { $example
+ "USING: printf ;"
+ "1234567890 \"%.5e\" printf"
+ "1.23456e+09" }
+ { $example
+ "USING: printf ;"
+ "12 \"%'#4d\" printf"
+ "##12" }
+ { $example
+ "USING: printf ;"
+ "1234 \"%+d\" printf"
+ "+1234" }
+} ;
+
+HELP: sprintf
+{ $values { "format-string" string } { "result" string } }
+{ $description "Returns the arguments (specified on the stack) formatted according to the format string as a result string." }
+{ $see-also printf } ;
+
+ARTICLE: "printf" "Formatted printing"
+"The " { $vocab-link "printf" } " vocabulary is used for formatted printing.\n"
+{ $subsection printf }
+{ $subsection sprintf }
+"\n"
+"Several format specifications exist for handling arguments of different types, and specifying attributes for the result string, including such things as maximum width, padding, and decimals.\n"
+{ $table
+ { "%%" "Single %" "" }
+ { "%P.Ds" "String format" "string" }
+ { "%P.DS" "String format uppercase" "string" }
+ { "%c" "Character format" "char" }
+ { "%C" "Character format uppercase" "char" }
+ { "%+Pd" "Integer format" "fixnum" }
+ { "%+P.De" "Scientific notation" "fixnum, float" }
+ { "%+P.DE" "Scientific notation" "fixnum, float" }
+ { "%+P.Df" "Fixed format" "fixnum, float" }
+ { "%+Px" "Hexadecimal" "hex" }
+ { "%+PX" "Hexadecimal uppercase" "hex" }
+}
+"\n"
+"A plus sign ('+') is used to optionally specify that the number should be formatted with a '+' preceeding it if positive.\n"
+"\n"
+"Padding ('P') is used to optionally specify the minimum width of the result string, the padding character, and the alignment. By default, the padding character defaults to a space and the alignment defaults to right-aligned. For example:\n"
+{ $list
+ "\"%5s\" formats a string padding with spaces up to 5 characters wide."
+ "\"%08d\" formats an integer padding with zeros up to 3 characters wide."
+ "\"%'#5f\" formats a float padding with '#' up to 3 characters wide."
+ "\"%-10d\" formats an integer to 10 characters wide and left-aligns."
+}
+"\n"
+"Digits ('D') is used to optionally specify the maximum digits in the result string. For example:\n"
+{ $list
+ "\"%.3s\" formats a string to truncate at 3 characters (from the left)."
+ "\"%.10f\" formats a float to pad-right with zeros up to 10 digits beyond the decimal point."
+ "\"%.5E\" formats a float into scientific notation with zeros up to 5 digits beyond the decimal point, but before the exponent."
+} ;
+
+ABOUT: "printf"
+
+
[ "%s" sprintf ] must-infer
+[ t ] [ "" "" sprintf = ] unit-test
+
+[ t ] [ "asdf" "asdf" sprintf = ] unit-test
+
[ t ] [ "10" 10 "%d" sprintf = ] unit-test
[ t ] [ "+10" 10 "%+d" sprintf = ] unit-test