Towards Freedom


Information, Inspiration, Imagination
truly a site for soaring Is

Clojure

Clojure programming notes

WHERNTO: techniq 

image of Clojure

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

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

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

  1. 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)

  1. 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

  1. 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

<2020-07-24 Fri> figured out how to install own work to .m2 started rewrite of algolyze using these ideas <2020-07-23 Thu> 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. <2020-07-22 Wed> got nuen.clj v1 done and testing.

<2020-07-18 Sat> go thru clojure reader is unsafe post about times post about project mechanism

<2020-07-17 Fri> 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

<2020-07-16 Thu> start nuen

rewrite anulysis for tech.ml rewrite anulysis for arrays

<2020-07-15 Wed> 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?

<2020-07-14 Tue> finishing mikera and incanter we should go through cheatsheet items and understand how the main functions in the categories work

<2020-07-13 Mon> 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

<2020-07-10 Fri> 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

<2020-07-09 Thu> anulysis finish hopefully

plan for manual trading

  1. examine situation around 12am
  2. put in suitable entry limit or stop trades with sltp
  3. try to exit trade around 12pm next day
  4. close orders and start at 1 again

<2020-07-08 Wed> 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)))))))

<2020-07-07 Tue> 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

<2020-07-06 Mon> 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. <2020-07-05 Sun> setup nu-orders.clj for populating nu with orders <2020-07-04 Sat> finish anulysis <2020-07-03 Fri> go through google hits example

<2020-07-02 Thu> 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.

<2020-07-01 Wed> issues with datasets and matrices using map and apply figured out a lot about for loop <2020-06-30 Tue> dilemmas with figuring out how to work hilo with nus <2020-06-29 Mon> figuring out a more iterative anulysis <2020-06-28 Sun> work on sicp - understanding cond and if <2020-06-27 Sat> started sicp and INDUCTIVESYNTHESISOFFUNCTIONALPROGRAMS

<2020-06-26 Fri> figure out mechanism to compare hilo to stacked nu problem is that i keep wanting to put things into boxes rather than thinking functionally.

<2020-06-25 Thu> 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

<2020-06-24 Wed> 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])

<2020-06-23 Tue> 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

<2020-06-22 Mon> started anulysis

<2020-06-21 Sun> 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!

<2020-06-20 Sat> 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)

<2020-06-19 Fri> investigating various things all week without entry into diary many of clojure.core.matrix is replacing the incanter functions: see updates to incanter 2.0 https://github.com/incanter/incanter/wiki/Incanter-2.0-change-log so we investigate these in datmat.clj

<2020-06-11 Thu> get-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.

<2020-06-10 Wed> 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.

<2020-06-09 Tue> 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

<2020-06-08 Mon> 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

<2020-06-07 Sun> installed inlein started thinking bayes

<2020-06-06 Sat> 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 clj A Brief Beginner's Guide To Clojure

<2020-06-05 Fri> more 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

<2020-06-04 Thu> 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

<2020-06-03 Wed> 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

<2020-06-02 Tue> 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.

<2020-06-01 Mon> understood the hobbit setup mostly in brave it is messy using loop, but much messier other ways

<2020-05-31 Sun> 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

<2020-05-30 Sat> figuring out git mostly getting through brave ch3 except last exercise

<2020-05-29 Fri> started clojure for brave updated several youtube resources

<2020-05-28 Thu> finished cds introduction

<2020-05-27 Wed> halfway through cds introduction why clojure video by vijay is useful

<2020-05-26 Tue> continued with cds set up resources and videos watched russ olsen functional programming in 40 min

<2020-05-25 Mon> set up emacs for clojure watched rick hickey video on creating it got cider and lein working started cds tutorial