WHERNTO: techniq
Clojure is a dynamic, general-purpose programming language, combining the approachability and interactive development of a scripting language with an efficient and robust infrastructure for multithreaded programming.
keybindings
Most are found in cider key ref and should be figured out gradually.
;; docs
C-h . Gives from lsp in eldoc buffer with examples (auto)
(C-u) C-c C-d C-d|w At point (prompt) docs local|web
C-c C-d C-a Apropos for function/var
C-c C-d C-f Apropos for text in documentation
C-c C-d C-e Apropos for text and select !!!
M-. Gives actual code
;; evaluate
C-c C-b Exit evaluation if stuck
C-c C-c Entire current form
C-c C-v C-l Immediate form
C-c|x C-e Previous form
C-c C-k Buffer
C-c M-; Output as comment
C-c M-e Output to REPL
(C-u) C-c C-(M-)l File(s)
C-c C-v (C-)l List
C-c C-v r Region
C-c C-v n The ns form
C-c C-v w Replace form with evaluation
C-c C-v z Preceding top form up to point !!!
;; help
C-h f cider-mode RET
;; launch
C-c M-j Do cider-jack-in-clj
C-c C-x C-x Prompt for choice of REPL
;; macros !!!
C-c C-m Macroexpand !!!
;; move
M-, Return to pre-jump location
C-M-d Down into list
C-M-u Up out of list
C-M-n Forward to next list
C-M-p Backward to prev list
C-M-h Next defun
C-M-@ Next sexp
C-M-f Forward by sexp
C-M-b Backward by sexp
C-M-a Descend into sexp
;; pprint
C-c C-v C-f e|d Pretty print last|current form to popup buffer
;; search
C-c C-d (C-)a Apropos var
C-c C-d (C-)f Apropos doc
;; switch
C-c C-z To relevant REPL
C-c M-z To relevant REPL after eval current buffer
C-c M-n M-n REPL ns to ns of current buffer
;; zzmisc
M-TAB Complete symbol at point
C-c M-d Display REPL connection info
C-c C-o Clear REPL output
C-c M-i Inspect and act on expression
(C-u) C-c C-z REPL jump
C-c M-p Insert form into REPL
C-c C-q Quit the REPL
cider manual
Home
Overview
Programmers are expected to program in a very dynamic and incremental manner, constantly re-evaluating existing Clojure definitions and adding new ones to their running applications.
Features
We need to understand these better to make full use of CIDER.
- Interactive code evaluation can do this right in the code with C-c M-; often more useful than repl
- Powerful REPL
- Code completion
- Code reloading
- Definition & documentation lookup particularly excellent with C-c d d
- Enhanced syntax highlighting and indentation
- Enhanced error reporting
- clojure.test integration
- clojure.spec integration
- Interactive debugger
- Data Inspector
- Integration with Java logging frameworks
- Profiling & tracing
- ClojureScript support
CIDER in Action
Videos are good for learning CIDER.
What’s Next?
Get familiar with interactive programming and cider-mode
Getting started
Installation
Already done.
Up and Running
Most of this is already setup, but we should look at:
- Jacking-in without a Project just clj to get the repl or can also use in a dir M-x cider-jack-in-universal
- Connect to a Running nREPL Server after getting a repl running M-x cider-connect for a port
nREPL Middleware Setup
You can skip this section if you don’t plan to use cider-connect or don’t care about the advanced functionality that requires cider-nrepl. However, with tools.deps we can add to ~/.clojure/deps.edn
:cider-clj {:extra-deps {cider/cider-nrepl {:mvn/version "0.49.0"}}
:main-opts ["-m" "nrepl.cmdline" "--middleware" "[cider.nrepl/cider-middleware]"]}
:cider-cljs {:extra-deps {org.clojure/clojurescript {:mvn/version "1.10.339"}
cider/cider-nrepl {:mvn/version "0.49.0"}
cider/piggieback {:mvn/version "0.5.3"}}
:main-opts ["-m" "nrepl.cmdline" "--middleware"
"[cider.nrepl/cider-middleware,cider.piggieback/wrap-cljs-repl]"]}
And can then run M-x cider-connect to the repl.
ClojureScript Setup
- Overview
- Up and Running
- Configuration
- Using Figwheel
- Using shadow-cljs
Using Other REPLs
Alternative Platforms
- Overview
- Babashka
- Nbb
- Other Platforms
Using CIDER
Interactive Programming
- Overview Instead of repeatedly editing, compiling, and restarting an application, the programmer starts the application once and then adds and updates individual Clojure definitions as the program continues to run … some Clojure programmers have been known to keep a CIDER session running for weeks or even months!
- Implementation
- Demos
Deep Dive into CIDER
Emacs & Clojure, A Lispy Love Affair \\
Using cider-mode
C-h f cider-mode is useful, but even better is using which-key-mode to see all key possibilities.
Code Evaluation
- Basic: buffer (do first)
- Exotic: should be accessed via CIDER’s evaluation commands keymap, prefix C-c C-v
- Minibuffer: cider-read-and-eval C-c M-:
- Evaluation hooks: ??
- Synchronous vs Asynchronous: nrn
- Configuration: nrn
- Keybindings: C-M-x, C-c C-c, C-c C-v [C-]d
Code Completion
- Standard: TAB or M-TAB (setq tab-always-indent 'complete)
- Completion styles: user may want to use a different completion style just for the CIDER complete eg (add-to-list 'completion-category-overrides '(cider (styles basic)))
- Auto-completion: with company or corfu (latter already setup via codeium) - not sure if codeium conflicts with corfu or cider when doing its suggestions or incorporates those completions into the suggestions, but it is really not too important.
Code Reloading
Clean everything up and reload one or more namespaces cider-ns-refresh, cider-ns-reload or cider-ns-reload-all
Pretty Printing
Probably NA.
Dealing with Errors
Most of the time CIDER will display the errors in a dedicated buffer … At times, the error being displayed will originate from a bug in CIDER itself. Error displays can be configured.
CIDER presents stack traces in a special major mode, cider-stacktrace-mode. There is a lot that can be done here, so it is worth knowing how to use.
Working with Documentation
C-h . should be initial ref which provides the clojuredocs examples. However, C-c C-d C-d|w can also be useful because the window is easy to close and the latter goes right to clojuredocs. If you want the javadoc use C-c C-d C-j to see it in browser.
Search in docstrings of all loaded variables with C-c C-d C-e|f which can be quite useful if you know only some words in a doc, but don't really know what the item is.
Cross referencing other documentation can be done inside `` or in same namespace or outside (fqdn required). Useful if you’d like to be able to point other programmers at different definitions.
Managing Connections
Misc Features
Using the REPL
Basic Usage
Keybindings
Configuration
REPL History
Testing
Running Tests
Test Reports
Supported Libraries
Debugging
Debugger
Enlighten
Inspector
Logging
Macroexpansion
Profiling
Tracing
Configuration
Indentation Specification
Caveats
Troubleshooting
FAQ
Additional Packages
Additional Resources
basics
- install: M-x package-install <RET> cider <RET>
-
run: launch an nREPL or connect to an existing one
- C-c C-x C-x gives menu of REPL choices (view in messsage buffer)
- C-c M-j cider-jack-in-clj (can run a repl without a project)
- supported build tools: clojure-cli, leiningen, babashka, nbb
- jack-in behavior can be customized or over-ridden
- remote and socket connections are possible too
- there are many advanced features possible with additional nREPL
- quit: C-c C-q kills REPL
using
- activate: with (add-hook 'clojure-mode-hook #'cider-mode) or M-x cider-mode (toggle)
- evaluate: C-c C-k (buffer), C-c C-e (previous form), C-c C-c (current form)
- interrupt: C-c C-b (stuck)
- jump to/from: C-c C-z (repl), C-u C-c C-z (match namespace)
- ref: C-c C-d C-d|w (docs), M-. (def, but lsp auto-shows)
- search: C-c C-d (C-)a (var), C-c C-d (C-)f (apropos doc)
enlive
A selector-based (à la CSS) templating library for Clojure.
group-by problem
stackoverflow tests interesting item to look at Group-by too slow (13 million-lines file) the solution is very instructive and covers generating a test file as well as timing.
hiccup
A
IO
csv read
(defn csv-read
"reads a csv file given filename"
[filename]
(map s/trim
(first (with-open
[in-file (clojure.java.io/reader filename)]
(doall
(clojure.data.csv/read-csv (clojure.java.io/reader in-file)))))))
loop-recur
from nuen 200708
(fn [rs nu-seq]
(loop [nu nu-seq
brs 0
prs 0
i 0]
(if (or (> i (- dohlc-size part-size))
(empty? nu))
[brs prs]
(let [nu0 (first nu-seq)
hi ($ i :h dohlc)
lo ($ i :l dohlc)
cl ($ i :c dohlc)
[is-brs is-prs] (if (= rs "r")
[(brs? nu0 hi cl < -) (prs? nu0 hi cl > +)]
[(brs? nu0 lo cl > +) (prs? nu0 lo cl < -)])
]
(cond
is-brs (recur nu (inc brs) prs (inc i))
is-prs (recur (drop 1 nu) brs (inc prs) (inc i))
:else (recur nu brs prs (inc i)))))))
project start
Simplest way to start project using cornfeld's clj-new.
clj -X:new-app :name pradesigner/myapp
clj -X:new-lib :name pradesigner/mylib
after adding to ~/.clojure/deps.edn: ;; add these into your :aliases map:
:new-app {:extra-deps {com.github.seancorfield/clj-new
{:mvn/version "1.1.309"}}
:exec-fn clj-new/create
:exec-args {:template "app"}}
:new-lib {:extra-deps {com.github.seancorfield/clj-new
{:mvn/version "1.1.309"}}
:exec-fn clj-new/create
:exec-args {:template "lib"}}}
deps.edn can help you figure out how to do things because of aliases :run-x :uberjar etc contains howto instructions! clj -X:run-x clj -X:uberjar
regex
Clojure Regex Tutorial by Eric Normand
Construct using a literal syntax: #"regex". Don't need to double escape #"\d" (match one digit).
Matching a regex to a string with groups
Match an entire string with re-matches.
(re-matches regex string) ;;=> result
;; No match returns nil
(re-matches #"abc" "xyz") ;;=> nil
(re-matches #"abc" "zzzabcxxx") ;;=> nil
;; Matching with no groups returns the matched string (truthy)
(re-matches #"abc" "abc") ;;=> "abc"
(re-matches #"\d+" "3324") ;;=> "3324"
;; Matching with groups returns a vector
(re-matches #"abc(.*)" "abcxyz") ;;=> ["abcxyz" "xyz"]
(re-matches #"(a+)(b+)(\d+)" "abb234") ;;=> ["abb234" "a" "bb" "234"]
Finding a regex substring within a string with groups
Using re-find returns the first match within the string. It can also be used to see if one string contains another though clojure.string/includes? is likely a better choice.
(re-find regex string)
;; No match returns nil
(re-find #"sss" "Loch Ness") ;;=> nil
;; Match without groups returns the matched string
(re-find #"s+" "mississipi") ;;=> "ss"
;; Match with groups returns a vector
(re-find #"s+(.*)(s+)" "success") ;;=> ["success" "ucces" "s"]
Finding all substrings that match within a string
Return a lazy seq of all of the matches with re-seq.
(re-seq regex string)
(re-seq #"s+" "mississippi") ;;=> ("ss" "ss")
(re-seq #"[a-zA-Z](\d+)"
"abc x123 b44 234") ;;=> (["x123" "123"] ["b44" "44"])
Replacing regex matches within a string
Replace all or first substring that matches with some other string with a string or a calculated function using clojure.string/replace.
(clojure.string/replace string regex replacement)
(str/replace "mississippi" #"i.." "obb") ;;=> "mobbobbobbi"
(str/replace "mississippi" #"(i)" "$1$1") ;;=> "miissiissiippii"
(str/replace "mississippi"
#"(.)i(.)"
(fn [[_ b a]]
(str (str/upper-case b)
"—"
(str/upper-case a)))) ;;=> "M—SS—SS—Ppi" !!!
Splitting a string by a regex
To split a string on some character pattern, like one or more whitespace use clojure.string/split.
(clojure.string/split string regex)
(str/split "This is a string that I am splitting." #"\s+")
;;=> ["This" "is" "a" "string" "that" "I" "am" "splitting."]
String contains a substring
Various ways to determine if there is a substring in a string.
(re-find #"needle" "Find a needle in a haystack.") ;;=> "needle"
(re-find #"needle" "Empty haystack.") ;;=> nil
(str/includes? "Find a needle in a haystack." "needle") ;;=> true
(str/includes? "Empty haystack." "needle") ;;=> false
(re-find #"^This string" "This string starts with ...") ;;=> "This string"
(re-find #"end$" "Find a string at the end") ;;=> "end"
(str/starts-with? "This string starts with ..." "This string") ;;=> true
(str/ends-with? "Find a string at the end" "end") ;;=> true
Escaping regex
Trying to match a regex symbol containing string can be done with java.util.regex.Pattern and is much preferable to trying to escape escapes (which can't be done anyway).
"(??^$]" ;; A string I want to match literally
#"\(\?\?\^\$\]" ;; you can't escape the escapes!
(Pattern/quote "(??^$]") ;;=> "\\Q(??^$]\\E"
(-> "(??^$]" Pattern/quote Pattern/compile) ;;=> #"\Q(??^$]\E" !!!
Joining regex
howto combine strings and regex https://stackoverflow.com/questions/21416917/multiple-regular-expressions-in-clojure
(defn union-regex [& patterns]
\\\"joins regex together\" with |\"
(re-pattern
(apply str
(interpose \""|"
(map #(str "(" % ")")
patterns)))))
(union-regex #"\w+ " (re-pattern w) " " #"\w+") ;; w set to "how"
=> #"(\w+ )|(how)|( )|(\w+)"
or this solution from webscraper project
(defn join-regex [& patterns]
"joins regex together"
(re-pattern
(apply str
(map #(str %)
patterns))))
(join-regex #"\w+ " (re-pattern w) " " #"\w+") ;; w set to "how"
=> #"\w+ how \w+"
Extract whole sentences with matching word
https://stackoverflow.com/questions/26081820/regular-expression-to-extract-whole-sentences-with-matching-word [^.]* flung [^.]*\. [^.?!]*(?<=[.?\s!])flung(?=[\s.?!])[^.?!]*[.?!]
scrapers
string
clojure.string functions
blank?
capitalize
ends-with?
escape
includes?
index-of
join
last-index-of
lower-case
re-quote-replacement
replace
replace-first
reverse
split
split-lines
starts-with?
trim
trim-newline
triml
trimr
upper-case
official clojure site
Use clojure.org as a reference for working with Clojure, but also put in specifics about own setup and tools.
Overview
- Why Clojure?
- Lisp is a good thing
- Functional programming is a good thing
- Languages and Platforms
- Object Orientation is overrated
- Polymorphism is a good thing
- Concurrency and the multi-core future
Guides
-
LEARNING
-
Getting Started
- emacs editor
- eglot Eglot is the Emacs client for the Language Server Protocol (LSP), which provides advanced programming language support and features for code editing in Emacs. It can do Language Server Integration, Auto-Completion, Go to Definition (M-.), Find References (M-?), Error Highlighting and Code Diagnostics (with flymake), Signature Help, Refactoring Support.
- clojure-lsp don't need to use it directly as a mode because eglot looks after that, but it does need to be installed. For instance, Find references didn't work when it was not installed. Perplexity got this wrong.
- cider see details in cider section and look in the manual.
- Install Clojure
- Editors
- Structural Editing
-
-
REPL Programming
- Introduction
- Launching a basic REPL
- Basic Usage
- Data Visualization at the REPL
- Navigating namespaces
- Enhancing your REPL workflow
- Guidelines for REPL-Aided Development
- Community resources
- Troubleshooting
-
Learn Clojure
- Introduction
- Syntax
- Functions
- Sequential Collections
- Hashed Collections
- Flow Control
- Namespaces
- FAQ
-
LANGUAGE
- spec
- Reading Clojure Characters
- Destructuring
- Threading Macros
- Equality
- Comparators
- Reader Conditionals
- Higher Order Functions
-
USAGE
- Dev Startup Time
-
TOOLS
- Deps and CLI
- tools.build
-
LIBRARIES
- core.async Walkthrough
- Go Block Best Practices
- test.check
Reference
- Reader forms
- Macro characters
- Tagged Literals
- Reader Conditionals
Community
- Success Stories
- Community Stories
- Companies
- Tools
- Libraries
- Contributing
- Community Resources
- Forum
- Events
- Training
- Etiquette
- HELP
- Books
- User Groups
- Starting a User Group
- SITE UPDATES
- Site Contributions
- Editing tips
- License
- Privacy Policy
- ETC
- Swag
API
- Clojure API
- ClojureScript API
- Clojure Contrib Libraries
- Other resources: ClojureDocs and cljdoc
DEV
- LANGUAGE DEV
- Development
- Contributor Agreement
- Workflow
- Creating Tickets
- Developing Patches
- Screening Tickets
- Contributors
- CONTRIB LIBS
- Contrib libs
- Contrib lib history
- RESOURCES
- Source
- Support Portal
- Issue Tracker
- Downloads
- API Docs
- License
Releases
- CLOJURE
- Current Release
- Older Releases
- Dev Changelog
- Download key
- CLOJURE TOOLS
- Tools Releases
News
Ongoing and updated regularly.
Clojure website Clojure Documentation clojure cheatsheet CIDER ClojureDocs ask.clojure forum Pedestal kixi stats
websites
videos
zz
ideas
do programming with awareness of each function's io
snippets
alternate possibilities with or
(defn mk-tohlc
"creates the dataset with date, open, high, low, close from filename"
[fpath]
(let [time (or "t" "column-0")
open (or "o" "column-1")
high (or "h" "column-2")
low (or "l" "column-3")
close (or "c" "column-4")]
(rename-columns
(->dataset fpath {:header-row? false
:parser-fn {time :string
open :float32
high :float32
low :float32
close :float32}})
{time :time open :open high :high low :low close :close})))
files
https://stackoverflow.com/questions/8566531/listing-files-in-a-directory-in-clojure
(seq (.list (clojure.java.io/file ".")))
(map #(.getPath %)
(file-seq (clojure.java.io/file ".")))
file https://clojuredocs.org/clojure.java.io/file
fs - File system utilities for clojure https://github.com/Raynes/fs
;using regex
(def files
(filter #(re-find #"1D|4H" %)
(map #(.getPath %)
(file-seq (clojure.java.io/file "/zata/truefx")))))
;using string
(def files
(filter #(clojure.string/includes? % "1D")
(map #(.getPath %)
(file-seq (clojure.java.io/file "/zata/truefx")))))
;going through a vector
(def files
(map (fn [x]
(filter #(clojure.string/includes? % x)
(map #(.getPath %)
(file-seq (clojure.java.io/file "/zata/truefx")))))
["1D" "4H" "1D"]))
files from filepaths
(def filepaths
"produces a list of truefx path strings"
(flatten (map (fn [x]
(sort (filter #(str/includes? % x)
(map #(.getPath %)
(file-seq (clojure.java.io/file "/zata/truefx"))))))
["1D" "4H" "1H"])))
(def filenames
"extracts file names from file paths"
(map #(last %)
(map #(str/split % #"/")
filepaths)))
partitions and maxmin
since partition gives list, we need to apply max to each list we map the apply max over the partitions
(map #(apply max %) (partition 3 r))
removing nil
(filter #(not(nil? %)) [1 nil 2 3 nil 5])
(1 2 3 5)
(remove nil? [1 nil 2 3 nil 5])
(1 2 3 5)
finding nu
(defn nusr
"identifies sr-levels for instrument using nu"
[fp]
(let [[o h l c fn pf] (inst-info fp)
part-size 5
step-size 1
midpt (quot part-size 2)
hi (partition part-size step-size h)
lo (partition part-size step-size l)
n (remove nil? (map #(nu % max midpt) hi))
u (remove nil? (map #(nu % min midpt) lo))]
[:ns n :us u]))
(defn nu
"finds a nu given seq, maxmin, midpt of seq"
[sq maxmin midpt]
(let [midval (nth sq midpt)]
(when (= (apply maxmin sq) midval)
midval)))
(nusr (first truefx-filepaths))
combining vectors
problem came up trying to work with bounsr and penesr where we needed to take 2 vectors and generate a vector of vectors matching items in sequence:
[4 4 6] [7 8 9] => 4 7] [4 8] [6 9
(zipmap [4 4 6] [7 8 9]) => {4 8, 6 9} due to repetition of the 4 because it is a map
this thread Is there an equivalent for the Zip function in Clojure had 2 solutions:
(map vector [4 4 6] [7 8 9]) => ([4 7] [4 8] [6 9]) (partition 2 (interleave [1 2 3] [4 5 6])) => ((1 4) (2 5) (3 6))
(interleave [1 2 3] [4 5 6] [7 8 9]) (apply interleave 1 2 3] [4 5 6] [7 8 9)
or as a function
(defn zip [& colls] (partition (count colls) (apply interleave colls)))
diff btn map and apply
(apply F [1 2 3 4 5]) => (F 1 2 3 4 5) (map F [1 2 3 4 5]) => [(F 1) (F 2) (F 3) (F 4) (F 5)] https://stackoverflow.com/questions/2311528/clojure-apply-vs-map
Use a vector as a LIFO stack to check for balanced brackets
(require '[clojure.set :refer [map-invert]])
(defn balance [form]
(let [brackets {\[ \] \( \) \{ \}}
scan (fn [q x]
(cond
(brackets x) (conj q x)
((map-invert brackets) x)
(if (= (brackets (peek q)) x)
(pop q)
(throw
(ex-info
(str "Unmatched delimiter " x) {})))
:else q))]
(reduce scan [] form)))
(balance "(let [a (inc 1]) (+ a 2))")
ExceptionInfo Unmatched delimiter ]
(balance "(let [a (inc 1)] (+ a 2))")
[]
dataset vs matrix
(type (incanter/to-matrix ds)) mikera.arrayz.impl.JoinedArray or vectorz/matrix (type (m/array ds)) clojure.lang.PersistentVector
cmd | dataset | matrix | array | lazyseq |
head,tail | y | y | y | n |
take,drop | y | y | y | y |
getting stuff out of incanter dataset dohlc
clojure.core.matrix.impl.dataset.DataSet
- using $ producing lazyseq
his ($ :h dohlc) clojure.lang.LazySeq or (sel dohlc :cols :h) los ($ :l dohlc) clojure.lang.LazySeq or (sel dohlc :cols :l)
- using to-map producing persistent vectors
ds (d/to-map dohlc) clojure.lang.PersistentArrayMap his (:h ds) clojure.lang.PersistentVector los (:l ds) clojure.lang.PersistentVector
- using m/array producing vectorz
ds (d/to-map dohlc) clojure.lang.PersistentArrayMap his (m/array (:h ds)) mikera.vectorz.Vector los (m/array (:l ds)) mikera.vectorz.Vector can't (m/array ds) because clojure.lang.PersistentArrayMap cannot be cast to java.lang.Number though (type (m/array d)) clojure.lang.PersistentVector
sel vs $
it seems as though we can use $ for pretty well everything we use sel for (sel d :cols :h) <=> ($ :h d) (sel d :rows (range 2 11) :cols :d) <=> ($ (range 1 11) :d d) (sel d :rows 1 :cols :h) <=> (sel d :rows 1 :cols 2) <=> (sel d 1 2) <=> ($ 1 2 d) <=> ($ 1 :h d)
codeOLD
the ratios function doesn't produce same results as the individual codings we haven't figured out why or which is really correct (defn anulysisV2 " analyzes brs and prs price action on nu
dohlc dataset columns :d date :o open :h high :l low :c close identify nu using partition map bsr? psr? to hilo and determine how many of each " [filepath] (let [[dohlc filename pipfactor] (instrument-dohlc filepath) dohlc (d/select-rows dohlc (range 33)) dohlc-size (nrow dohlc) ;size of dataset less 2 because of header buffer (/ 12.0 pipfactor) ;buffer line calculation in pips for pair part-size 7 ;size of partition chosen [nseq useq] (nu-finder dohlc)
+brs? (fn [nu hilo cl >< -+]
"n: (brs? n hi cl < -) u: (bsr? u lo cl > )"
(and (btn? hilo (- nu buffer) ( nu buffer))
(>< cl (-+ nu buffer))))
prs? (fn [nu cl hilo >< -+]
"n: (prs? n hi cl > ) u: (prs? u lo cl < -"
(and (>< hilo (- nu buffer))
(>< cl nu)))
ratios (fn [rs nu-seq] (loop [nu nu-seq brs 0 prs 0 i 0] (let [nu0 (first nu-seq) hi ($ i :h dohlc) lo ($ i :l dohlc) cl ($ i :c dohlc) [is-brs is-prs] (if (= rs "r") [(brs? nu0 hi cl < -) (prs? nu0 hi cl > +)] [(brs? nu0 lo cl > +) (prs? nu0 lo cl < -)]) ] (if (> i (- dohlc-size part-size)) [brs prs] (cond is-brs (recur nu (inc brs) prs (inc i)) is-prs (recur (drop 1 nu) brs (inc prs) (inc i)) :else (recur nu brs prs (inc i))) ))))
n-ratio (loop [nn nseq brs 0 prs 0 i 0] (let [firstnn (first nn) hi ($ i :h dohlc) cl ($ i :c dohlc)] (if (> i (- dohlc-size part-size)) [brs prs] (cond (brs? firstnn hi cl < -) (recur nn (inc brs) prs (inc i)) (prs? firstnn hi cl > +) (recur (drop 1 nn) brs (inc prs) (inc i)) :else (recur nn brs prs (inc i))) ))) u-ratio (loop [uu useq brs 0 prs 0 i 0] (let [firstuu (first uu) lo ($ i :l dohlc) cl ($ i :c dohlc)] (if (> i (- dohlc-size part-size)) [brs prs] (cond (brs? firstuu lo cl > +) (recur uu (inc brs) prs (inc i)) (prs? firstuu lo cl < -) (recur (drop 1 uu) brs (inc prs) (inc i)) :else (recur uu brs prs (inc i))) ))) n-ratio (ratios "r" nseq) u-ratio (ratios "s" useq) ] [n-ratio u-ratio] ))
while the ideas here are ok we require 20s by not using partitions and 25ms when we do!! however, we need a way to figure out the index
(defn nu-finderV2 " finds nu give a dohlc dataset returns i nn] [i uu " [dohlc] (let [size (nrow dohlc) nu-breadth 7 ;nu width buf-bars (quot nu-breadth 2) ;number of bars on either side of nu ibeg buf-bars ;begining bar to look for nu iend (- (nrow dohlc) 1 buf-bars) ;ending bar to look for nu nu? (fn [i hilo maxmin] (= ($ i hilo dohlc) (apply maxmin ($ (range (- i buf-bars) (+ i buf-bars 1)) hilo dohlc)))) nus (fn [hilo maxmin] (loop [i ibeg iv []] (if (>= i iend) iv (if (nu? i hilo maxmin) (recur (+ i buf-bars 1) (conj iv [i ($ i hilo dohlc)])) (recur (inc i) iv)))))] [(nus :h max) (nus :l min)]))
(defn anulysisV1 " analyzes brs and prs price action on nu
dohlc dataset columns :d date :o open :h high :l low :c close identify nu using partition map bsr? psr? to hilo and determine how many of each " [filepath] (let [[dohlc filename pipfactor] (instrument-dohlc filepath) dohlc-size (nrow dohlc) ;size of dataset less 2 because of header buffer (/ 12.0 pipfactor) ;buffer line calculation in pips for pair part-size 7 ;size of partition chosen nn (nu-finder ($ :h dohlc) part-size max) uu (nu-finder ($ :l dohlc) part-size min) in-zone? (fn [hilo nu] (btn? hilo (- nu buffer) (+ nu buffer)))] (loop [i 4 brs 0] (if (> i (- dohlc-size 9)) brs (recur (inc i) (if (in-zone? ($ i :h dohlc) (first nn)) (inc brs) brs))) ) [(count nn) (count uu)]))
(defn mk-dohlc "creates the dataset with date, open, high, low, close from filename" [filename] (d/rename-columns (read-dataset filename) {:col0 :d :col1 :o :col2 :h :col3 :l :col4 :c}))
(defn nu-finderV1 " finds all nu in a sequence of hilo given a sequence, the partition size, max|min operator for his|los TODO have option to remove invalid nu " [aseq part-size maxmin] (let [partitions (partition part-size 1 aseq) midpt (quot part-size 2) nu (for [p partitions :when (= (apply maxmin p) (nth p midpt))] (nth p midpt))] nu))
(def truefx-filepaths "produces a list of truefx path strings" (vectorize (flatten (map (fn [x] (sort (filter #(str/includes? % x) (map #(.getPath %) (file-seq (clojure.java.io/file "/zata/truefx")))))) ["1D" "4H" "1H"]))))
(defn adjacent-confluence "determines oc confluence behavior of adjacent bars" [fp] (let [dohlc (mk-dohlc fp) fn (filename-from-filepath fp) pf (pip-factor fn) m (to-matrix (ds/remove-columns dohlc [:d])) o (sel m :cols 0) h (sel m :cols 1) l (sel m :cols 2) c (sel m :cols 3) co (map pips c o (repeat pf)) pn (map #(pos? (* %1 %2)) co (drop 1 co)) p% (Math/round (/ (count (filter true? pn)) (float (count pn)) 0.01))] (printf "%s %d %n" fn p%) p%))
to-solve
match a key and print component of a map
here is a vector of maps (def asym-parts [{:name "head" :size 3} {:name "mouth" :size 1} {:name "nose" :size 1} {:name "neck" :size 2} {:name "left-eye" :size 1} {:name "left-ear" :size 1}to {:name "left-shoulder" :size 3}])
match the :name to be "nose" and print that item TODO
an interesting solution to something similar https://stackoverflow.com/questions/18176372/clojure-get-map-key-by-value
(->> {:a "bar" :b "foo" :c "bar" :d "baz"} ; initial map (group-by val) ; sorted into a new map based on value of each key (#(get % "bar")) ; extract the entries that had value "bar" (map key)) ; get the keys that had value bar or (map key (#(get % "bar") (group-by val {:a "bar" :b "foo" :c "bar" :d "baz"})))
old diary items
figured out how to install own work to .m2 started rewrite of algolyze using these ideas went through clojure style guide got better understanding of ns installed and worked with hylang - though we should check out cljpython too at some point
discussion on tech.ml was very promising with both gigasquid and joinr praising it. so that's what we'll go with for now - convert existing items to it and look for a visualization mechanism.
got nuen.clj v1 done and testing.go thru clojure reader is unsafe post about times post about project mechanism
nuen mostly done thx to help on clojurians
techml read into techml dataset a csv file nearly 3 million lines drop one column form new column the result of subtracting one column from another printout head of adjusted dataset
timings: lein run 62.93s user 0.86s system 123% cpu 51.800 total emacs repl "Elapsed time: 40112.441757 msecs" java -jar target/uberjar/techml-0.1.0-SNAPSHOT-standalone.jar 29.95s user 0.77s system 162% cpu 18.916 total
start nuen
rewrite anulysis for tech.ml rewrite anulysis for arrays
finish mikera and incanter build a matrix, dataset, array toolkit (mikera incanter and anything else) plan for clj cheatsheet explorations -> make own cheatsheet from it and others plan for java function access
will conversion to separate arrays be more efficient for subsequent processing? using arrays instead of incanter datasets may be practical?
finishing mikera and incanter we should go through cheatsheet items and understand how the main functions in the categories work
last couple of days were spent with julia programming. though the docs are excellent, emacs doesn't work too well with it right now. emacs does work well with R. so may be …
attempt to get python libraries on clojure using libpython-clj - but carin's example doesn't work completely. anyway, we don't really need to do this now because what we were interested in seeing was how well anulysis worked and we can actually do this better in other ways - such as plotting hlc dots with buffers from nu
checked out graalvm and that does look very interesting! again, we don't need it now, but it is definitely something to keep in mind for the future considering one demo showed 20 performance improvement. it may be useful even without its polyglot capabilities.
for now, here's what we focus on:
- learn mikera and incanter
- learn what we can do with direct access to java
- optimize anulysis
- get nuen completed
got R and candlesticks working - it's pretty good! main difficulty was that manjaro doesn't autoload make and gcc-fortran
plotly.clj doesn't seem to have candlesticks plan is to go through incanter plotting and compare to plotly.clj plotting
anulysis finish hopefully
plan for manual trading
- examine situation around 12am
- put in suitable entry limit or stop trades with sltp
- try to exit trade around 12pm next day
- close orders and start at 1 again
cider site debugging cider debugging tools debugging in clojure several items not quite understood but we now have a useable debugging mechanism
more learnt about loop-recur in that the main if statement can have various forms (eg let) in true or false. this knowledge enabled the best version to-date: (fn [rs nu-seq] (loop [nu nu-seq brs 0 prs 0 i 0] (if (or (> i (- dohlc-size part-size)) (empty? nu)) [brs prs] (let [nu0 (first nu-seq) hi ($ i :h dohlc) lo ($ i :l dohlc) cl ($ i :c dohlc) [is-brs is-prs] (if (= rs "r") [(brs? nu0 hi cl < -) (prs? nu0 hi cl > +)] [(brs? nu0 lo cl > +) (prs? nu0 lo cl < -)]) ] (cond is-brs (recur nu (inc brs) prs (inc i)) is-prs (recur (drop 1 nu) brs (inc prs) (inc i)) :else (recur nu brs prs (inc i)))))))
getting nu the partition mechanism provides far faster results than iterating over groups of 7 bars - even if you skip bars regularly because after a nu the latter three can never be a nu. however, the partitions don't provide anyway of keeping track of the index. a problem can develop in that as we go through nu we could be counting brs even before the occurence of the nu!
so here are 2 ideas: figure out the index of the nu through a loop-recur setup. something like loop ds to find index conj index+accumulatedindices to nu drop index+1 ds
similar idea, but we don't need to actually put the index anywhere. find index of nu drop to index+1 start to check for brs once prs drop current nu do over again this way we only start checking for brs after we find where the nu is
figured out how to use loop-recur better - it is a likeable combo and seems preferable to me than recursion now. got a good version of nu-finder done which includes index amongst other things and can be used outside anulysis. setup nu-orders.clj for populating nu with orders finish anulysis go through google hits example
determine whether to use core.matrix or incanter for most things incanter is being incorporated within core.matrix and it is not really developed much. so we'll make the switch and start looking at some of the other data science libraries.
discovered core.matrix creator mike anderson or mikera who has good youtube videos on the topic
seems as though core.matrix (most operations) and incanter (rw graphics etc) can work well together.
issues with datasets and matrices using map and apply figured out a lot about for loop dilemmas with figuring out how to work hilo with nus figuring out a more iterative anulysis work on sicp - understanding cond and if started sicp and INDUCTIVESYNTHESISOFFUNCTIONALPROGRAMS
figure out mechanism to compare hilo to stacked nu problem is that i keep wanting to put things into boxes rather than thinking functionally.
work on anulysis using stacks and proper influence.
(def d (ds/select-rows ds (range 9))) (ds/add-column d :sums (mt/add (sel d :cols :o) (sel d :cols :h))) (ds/add-column d :sums (mt/gt (sel d :cols :c) 83)) (ds/add-column d :sums (mt/mul (sel d :cols :c) (mt/gt (sel d :cols :c) 83))) ;crude
creating bounsr and penesr functions within let got involved with creating pairs
though there are some nice ideas in V1 of anulysis the overall attempt to have nu checked over the entire matrix is meaningless and produced absurdly high numbers - eg almost 8000 bounsr for nrow = 2248. so we need to restrict the nu influence to forward items only and have them flip after first penesr and disappear after a second penesr.
(defn anulysisV1 "analyzes pa near nu" [fp] (let [[ops his los cls fnm pf] (instrument-info fp) buffer (/ 12 pf) bounsr? (fn [nus hilos cls >< -+] (count (remove nil? (for [nu nus [hilo cl] (zip hilos cls)] (let [nu-buffer (-+ nu buffer)] (if (and (btn? hilo [nu nu-buffer]) (>< nu-buffer cl)) true)))))) bpsr? (fn [nus hilos ops cls >< -+] (for [nu nus [hilo op cl] (zip hilos ops cls)] (let [b-buffer (-+ nu buffer) p-buffer (-+ nu (- buffer))] (cond (and (btn? hilo [nu b-buffer]) (>< b-buffer cl)) :bounsr (and (btn? nu [op cl]) ) :penesr)))) part-size 5 midpt (quot part-size 2) hi-partition (partition part-size 1 his) lo-partition (partition part-size 1 los) nn (remove nil? (map #(nu-finder % max midpt) hi-partition)) uu (remove nil? (map #(nu-finder % min midpt) lo-partition)) boun-s (bounsr? uu los cls < +) boun-r (bounsr? nn his cls > -)
isbounsr #(= :bounsr %) ispenesr #(= :penesr %) bpu (bpsr? uu los ops cls < +) bpn (bpsr? nn his ops cls > -) ] [fnm boun-s boun-r (count (filter isbounsr bpu)) (count (filter isbounsr bpn)) (count (filter ispenesr bpu)) (count (filter ispenesr bpn))]))
(map anulysis (take 1 truefx-filepaths)) => (["audjpy1D.csv" 3829 3607]) => (["audjpy1D.csv" 4167 4035])
coined term lalwal lose a little win a lot rewrote outliers in truefx files - all were with the lows. some involving CHF may have been legitimate. anulysis almost done after figuring out that :while is not to be used with for - not sure what it is
started anulysis
get barchar working first idea of adjacent-confluence may work in reverse for shorter tf
started snippets in this file
made neat ns discovry - whatever is in core.clj including def/defn becomes available to every other file provided the namespace isn't changed! this really means that we can load up core.clj with whatever is required rather than import everything for every related program we create!
working with dataset functions add-column, reorder-column, remove-column wrote sel-col function which is useful to work with single column in dataset
discovered that sel on a dataset is very slow compared to sel on a matrix it seems to be far, far faster to convert a dataset to a matrix to do things and then convert it back if you want to utilize the variety of types a dataset offers. (see xpts in datmat.clj)
https://github.com/incanter/incanter/wiki/Incanter-2.0-change-log so we investigate these in datmat.clj
investigating various things all week without entry into diary many of clojure.core.matrix is replacing the incanter functions: see updates to incanter 2.0get-orders-for done rearrange the ztut which was getting awkward as far as ns goes as well as other things. set it all up on gitlab
changing to ns works with C-c M-n after we C-c C-k the buffer. for some reason, (in-ns namespace) doesn't always work. this page is useful as may be other things on that site.
incanter things work nicely so far, but we need to become far more knowledgeable working with datasets, functions (what they do) and plotting.
also, the how i start thing is a bit confusing as carin jumps to things that we're not familiar with so we'll get back to that later.
incanter:
-
work through data sorcery
- cheatsheet use regularly to recall syntax and concepts
- make use of api documentation throughout
- namespace switching solved: repl takes main ns, but can switch with (in-ns 'whatever) so long as it is seen
- started How I Start which should be useful for namespace understanding and testing
incanter:
- work through ch6 Working with Incanter Datasets from Clojure Data Analysis Cookbook which was helpful though the datasets used were huge and therefore difficult to examine in some situations
inlein started thinking bayes
installedA Brief Beginner's Guide To Clojure
transferred from github to gitlab which seems to be smoother and cleaner. cleaned up tutorials into ztut folder cleaned up clj bookmarks went through excellent birdseye view of cljmore cider it seems that form order is important because loading the buffer when dependencies don't come first makes eval impossible. cider has a lot of functions, but we need to figure out which ones we'll actually use successfully connected to an existing repl at localhost after getting port using: connection info C-c M-d
downloaded cheatsheets: clojuredocs
paredit:
M-( M-" | M-s M-? | C-right C-left | M-S M-J | C-M-f C-M-b |
cider:
C-c C-z | C-c M-j | C-c C-c | C-c C-k | C-up C-down |
got all of oanda ide to date as far as we had python going order fn greatly simplified - we never needed to use if-let
investigated cider further watched alchy bozbat
stuck on json not being parsed but that was because clojure follows the curl more closely using :body instead of :json whereas python didn't
get api functions and sring theory to where we were with python all api done as far as python progress except for the json issue
hobbit problem using reduce is neatest
excellent video with edmund jackson data science and clojure shows the landscape in 2012 and what options there were then probably worth following up on this.
understood the hobbit setup mostly in brave it is messy using loop, but much messier other ways
set up tut structures in clojure directory set up problems to solve file in to-solve.clj file
Clojure Libs and Namespaces: require, use, import and ns (require 'clojure.string 'clojure.test) (require '[clojure.string :as string]) to avoid (require ['clojure.string :as 'string]) (require 'clojure.string '[clojure.test :as test]) (require '(clojure string test)) (require '(clojure [string :as string] test))
consider the incanter lib issue (use '(incanter core stats charts io)) works right away and we can call view, histogram etc (require '(incanter core stats charts io)) doesn't seem to work at all, but that's due to ns issues: (incanter.core/view (incanter.charts/histogram (incanter.stats/sample-normal 1000))) is just fine
also see Clojure Namespaces and Vars for better ways as well as this answer from stackoverflow. we can solve this with (ns tut-incanter.core (:require (incanter [core :refer :all] [stats :refer :all] [charts :refer :all]))) though (use '(incanter core stats charts)) seems much simpler
both api requests with clj-http and json readability accomplished next step is to get functions to work
figuring out git mostly getting through brave ch3 except last exercise
started clojure for brave updated several youtube resources
finished cds introduction
halfway through cds introduction why clojure video by vijay is useful
functional programming in 40 min
continued with cds set up resources and videos watched russ olsenset up emacs for clojure watched rick hickey video on creating it got cider and lein working started cds tutorial