diff --git a/lib/algo/deps.edn b/lib/algo/deps.edn index 56c42c28..2ad08357 100644 --- a/lib/algo/deps.edn +++ b/lib/algo/deps.edn @@ -1,4 +1,4 @@ -{:paths ["src"] +{:paths ["src" "resources"] :deps {org.clojure/clojure {:mvn/version "1.11.1"} ta/db {:local/root "../db" :deps/manifest :deps} ; bar-db diff --git a/lib/algo/resources/quanta/notebook/algo_aligned.clj b/lib/algo/resources/quanta/notebook/algo_aligned.clj new file mode 100644 index 00000000..3e99f945 --- /dev/null +++ b/lib/algo/resources/quanta/notebook/algo_aligned.clj @@ -0,0 +1,40 @@ +(ns quanta.notebook.algo-aligned + (:require + [tick.core :as t] + [modular.system] + [taoensso.timbre :refer [trace debug info warn error]] + [tablecloth.api :as tc] + [ta.algo.env.core :refer [get-bars-aligned-filled]] + [ta.calendar.core :as cal] + [ta.env.backtest :refer [run-backtest]] + [ta.engine.javelin :refer [create-env]] + [ta.engine.javelin.algo :as dsl])) + +(defn get-aligned [env {:keys [calendar trailing-n] :as opts} time] + (let [cal-seq (cal/trailing-window calendar trailing-n time) + bars (get-bars-aligned-filled env opts cal-seq)] + {:time time + :cal-seq cal-seq + :bars bars})) + +(def window (-> (cal/trailing-range [:us :d] 1) + ;(window-as-date-time) + )) + +window + +(def spec {:asset "MSFT" + :calendar [:us :d] + :import :kibot + :trailing-n 100}) + +(def env (create-env :bardb-dynamic)) +(def strategy (dsl/add-time-strategy env spec get-aligned)) +(run-backtest env window) +@strategy + +(t/inst) + +(-> (t/inst) + (t/date) + (t/at (t/time "00:04:00"))) diff --git a/lib/algo/resources/quanta/notebook/algo_dummy.clj b/lib/algo/resources/quanta/notebook/algo_dummy.clj new file mode 100644 index 00000000..42bcf7a4 --- /dev/null +++ b/lib/algo/resources/quanta/notebook/algo_dummy.clj @@ -0,0 +1,82 @@ +(ns quanta.notebook.algo-dummy + (:require + [ta.calendar.core :as cal] + [ta.engine.protocol :as eng] + [ta.algo.env :as algo-env] + [ta.algo.backtest :refer [backtest-algo run-backtest]])) + +;; 1. time-based algo spec + +(defn secret [env spec time] + (str "the spec is: " spec " (calculated: " time ")")) + +(def spec {:type :time + :calendar [:us :d] + :data 42 + :algo 'quanta.notebook.algo-dummy/secret}) + +(def e (algo-env/create-env-javelin nil)) + +(def algo (algo-env/add-algo e spec)) + +algo + +;; 2. test algo calculation + +(def engine (algo-env/get-engine e)) + +engine + +(eng/set-calendar! engine {:calendar [:us :d] :time :evening}) + +algo +@algo +;; => "the spec is: {:type :time, :calendar [:us :d], :data 42, :algo notebook.playground.algo.dummy/secret} (calculated: :evening)" + +;; 3. backtest with complex syntax + +(def window (cal/trailing-range [:us :d] 1)) + +e +(run-backtest e window) + +@algo +;; => "the spec is: {:type :time, :calendar [:us :d], :data 42, :algo notebook.playground.algo.dummy/secret} (calculated: 2024-02-26T17:00-05:00[America/New_York])" + +;; 4. backtest with simple syntax + +(def result + (backtest-algo :duckdb spec)) + +@result +;; => "the spec is: {:type :time, :calendar [:us :d], :data 42, :algo notebook.playground.algo.dummy/secret} (calculated: 2024-02-26T17:00-05:00[America/New_York])" + +;; 5. backtest with formulas. + +(defn combine [env spec & args] + {:args args}) + +(defn sum [env spec & args] + (apply + args)) + +(def combined-spec + [:a {:calendar [:us :d] :algo 'quanta.notebook.algo-dummy/secret :type :time} + :b {:type :time :calendar [:us :d] :data 42 :algo 'quanta.notebook.algo-dummy/secret} + :c {:value 4444} + :d {:formula [:a :b] :algo 'quanta.notebook.algo-dummy/combine :type :time} + :e {:value 2222} + :f {:formula [:c :e] :algo 'quanta.notebook.algo-dummy/sum :type :time}]) + +(require '[ta.algo.spec.ops :refer [spec->ops]]) +(spec->ops e spec) +(spec->ops e combined-spec) + +(def combined-result + (backtest-algo :duckdb combined-spec)) + +@(:a combined-result) +@(:b combined-result) +@(:c combined-result) +@(:d combined-result) +@(:f combined-result) +combined-result diff --git a/lib/algo/resources/quanta/notebook/algo_tickerplant.clj b/lib/algo/resources/quanta/notebook/algo_tickerplant.clj new file mode 100644 index 00000000..c80efb7f --- /dev/null +++ b/lib/algo/resources/quanta/notebook/algo_tickerplant.clj @@ -0,0 +1,85 @@ +(ns quanta.notebook.algo-tickerplant + (:require + [modular.system] + [ta.live.tickerplant :refer [start-tickerplant current-bars]] + [ta.algo.env.protocol :as algo])) + +;; 1. get algo-env form clip + +(def algo-env (modular.system/system :live)) + +;; 2. possibly start tickerplant (it is already started via clip) + +(def quote-manager (modular.system/system :quote-manager)) + +(def t (start-tickerplant {:algo-env algo-env + :quote-manager quote-manager})) + +(def t (modular.system/system :tickerplant)) + +t + +;; define algo + +(defn nil-algo [_env _opts bar-ds] + bar-ds) + +(def algo-spec + [:eurusd-d {:type :trailing-bar + :trailing-n 80 + :calendar [:forex :h] + :asset "EUR/USD" + :feed :fx + :algo 'quanta.notebook.algo-tickerplant/nil-algo} + :usdjpy-m {:type :trailing-bar + :trailing-n 80 + :calendar [:forex :m] + :asset "USD/JPY" + :feed :fx + :algo 'quanta.notebook.algo-tickerplant/nil-algo} + :btc-m {:type :trailing-bar + :trailing-n 100 + :calendar [:crypto :m] + :asset "BTCUSDT" + :feed :crypto + :algo 'quanta.notebook.algo-tickerplant/nil-algo} + :eth-m {:type :trailing-bar + :trailing-n 100 + :calendar [:crypto :m] + :asset "ETHUSDT" + :feed :crypto + :algo 'quanta.notebook.algo-tickerplant/nil-algo} + + :dummy {:type :trailing-bar + :trailing-n 100 + :calendar [:us :m] + :asset "WILLY-WONKER" + ; note that no feed is defined, so no quotes will be subscribed, + ; and no bars will be generated. + :algo 'quanta.notebook.algo-tickerplant/nil-algo}]) + +(algo/add-algo algo-env algo-spec) + +(current-bars t [:forex :m]) +(current-bars t [:crypto :m]) + +;; => ({:asset "BTCUSD", :epoch 1} +;; {:asset "ETHUSDT", +;; :epoch 1, +;; :open 3404.72, +;; :high 3408.91, +;; :low 3402.64, +;; :close 3407.56, +;; :volume 961.2800100000002, +;; :ticks 1473}) + +;; => ({:asset "BTCUSD", :epoch 1} +;; {:asset "ETHUSDT", +;; :epoch 1, +;; :open 3404.72, +;; :high 3408.91, +;; :low 3402.64, +;; :close 3407.82, +;; :volume 944.0061100000004, +;; :ticks 1454}) + diff --git a/lib/calendar/deps.edn b/lib/calendar/deps.edn index 82f1f142..4fa0c176 100644 --- a/lib/calendar/deps.edn +++ b/lib/calendar/deps.edn @@ -1,6 +1,4 @@ -{:paths ["src" - ;"classes" - ] +{:paths ["src" "resources"] :deps {org.clojure/clojure {:mvn/version "1.11.1"} com.taoensso/timbre {:mvn/version "6.2.2"} ; clj/cljs logging jarohen/chime {:mvn/version "0.3.3"} ; scheduler diff --git a/lib/calendar/resources/quanta/notebook/calendar_combined.clj b/lib/calendar/resources/quanta/notebook/calendar_combined.clj new file mode 100644 index 00000000..bd9b24a0 --- /dev/null +++ b/lib/calendar/resources/quanta/notebook/calendar_combined.clj @@ -0,0 +1,30 @@ +(ns quanta.notebook.calendar-combined + (:require + [tick.core :as t] + [ta.calendar.combined :refer [window]] + [clojure.pprint :refer [print-table]])) + +(def start-dt (t/now)) +start-dt + +(def windows [[:crypto :h] + [:crypto :m]]) + +(defn print-n [windows days] + (let [end-dt (t/>> start-dt (t/new-duration days :days)) + c (window start-dt end-dt windows)] + (->> c + (print-table)))) + +(print-n [[:crypto :h] + [:crypto :m]] + 3) + +(print-n [[:eu :d] + [:us :d]] + 10) + +(print-n [[:test-short :d] + [:test-short :h] + [:test-short :m30]] + 30) \ No newline at end of file diff --git a/lib/calendar/resources/quanta/notebook/calendar_live_time.clj b/lib/calendar/resources/quanta/notebook/calendar_live_time.clj new file mode 100644 index 00000000..4f9dffe8 --- /dev/null +++ b/lib/calendar/resources/quanta/notebook/calendar_live_time.clj @@ -0,0 +1,21 @@ +(ns quanta.notebook.calendar-live-time + (:require + [taoensso.timbre :as timbre :refer [info warn error]] + [manifold.stream :as s] + [ta.live.calendar-time :as ct])) + +(def s (ct/create-live-calendar-time-generator)) + +(ct/add-calendar s [:us :m]) +(ct/add-calendar s [:crypto :m]) +(ct/add-calendar s [:forex :m]) +(ct/add-calendar s [:eu :m]) + +(s/consume + (fn [msg] + (info "time event: " msg)) + (ct/get-time-stream s)) + +(ct/remove-calendar s [:eu :m]) + +(ct/show-calendars s) \ No newline at end of file diff --git a/lib/calendar/resources/quanta/notebook/calendar_simple.clj b/lib/calendar/resources/quanta/notebook/calendar_simple.clj new file mode 100644 index 00000000..d5d7b291 --- /dev/null +++ b/lib/calendar/resources/quanta/notebook/calendar_simple.clj @@ -0,0 +1,16 @@ +(ns quanta.notebook.calendar-simple + (:require + [ta.calendar.core :refer [calendar-seq]] + [clojure.pprint :refer [print-table]])) + +(def c (calendar-seq :crypto :d)) + +(take 1 c) + +(take 10 c) + +(->> (take 1000 c) + (map println)) + + + diff --git a/lib/db/resources/quanta/notebook/asset_bybit.clj b/lib/db/resources/quanta/notebook/asset_bybit.clj new file mode 100644 index 00000000..f79adf43 --- /dev/null +++ b/lib/db/resources/quanta/notebook/asset_bybit.clj @@ -0,0 +1,17 @@ +(ns quanta.notebook.asset-bybit + (:require + [ta.import.provider.bybit.raw :refer [get-assets-spot]])) + +(defn save-list [assets] + (->> (map (fn [s] + {:name s + :symbol s + :category :crypto}) assets) + (pr-str) + (spit "resources/symbollist/bybit.edn"))) + +(-> (get-assets-spot) + (save-list)) + + + diff --git a/lib/db/resources/quanta/notebook/asset_db.clj b/lib/db/resources/quanta/notebook/asset_db.clj new file mode 100644 index 00000000..4925d6d3 --- /dev/null +++ b/lib/db/resources/quanta/notebook/asset_db.clj @@ -0,0 +1,45 @@ +(ns quanta.notebook.asset-db + (:require + [ta.db.asset.db :as db] + [clojure.pprint :refer [print-table]])) + +(db/search "P") +(db/search "Bitc") +(db/search "BT") +(db/search "Aura") + +(db/search "BT" :crypto) +(db/search "B" :equity) +(db/search "B" :equity "SG") +(db/search "B" nil nil) +(db/search "B" "" "") + +(db/instrument-details "BTCUSD") +(db/instrument-details "EUR/USD") +(db/instrument-name "BTCUSD") + +(-> (db/get-instruments) + print-table) + +(db/get-instruments) + +(db/symbols-available :crypto) +(db/symbols-available :etf) +(db/symbols-available :equity) +(db/symbols-available :fx) +(db/symbols-available :future) + +(db/instrument-details "NG0") +;; => {:symbol "NG0", :kibot "NG", :name "CONTINUOUS NATURAL GAS CONTRACT", :category :future, :exchange "SG"} + +(db/instrument-details "NG1223") + ;; => {:symbol "NG1223", :kibot "NGZ23", :name "CONTINUOUS NATURAL GAS CONTRACT", :category :future, :exchange "SG"} + +(vals @db/db) + +(db/get-instrument-by-provider :kibot "NG") +(db/get-instrument-by-provider :kibot "XXXXXX") + +(db/modify {:symbol "MSFT" :super 3}) + +(db/instrument-details "MSFT") \ No newline at end of file diff --git a/lib/db/resources/quanta/notebook/asset_eodhd.clj b/lib/db/resources/quanta/notebook/asset_eodhd.clj new file mode 100644 index 00000000..fb2f9df2 --- /dev/null +++ b/lib/db/resources/quanta/notebook/asset_eodhd.clj @@ -0,0 +1,43 @@ +(ns quanta.notebook.asset-eodhd + (:require + [ta.import.provider.eodhd.raw :refer [get-exchanges get-exchange-tickers]])) + +(def api-token "65f0ad82c56400.56029279") + +(def e (get-exchanges api-token)) + +(spit "resources/eodhd-exchanges.edn" (pr-str e)) + +(def t (get-exchange-tickers api-token "AU")) + +t + +(defn convert-one [{:keys [Code Name Country Exchange Isin Type Currency] :as eodhd-one}] + {:symbol (str Code "." Exchange) + :name Name + :category :stock + :region :australia + :isin Isin}) + +(defn filter-stocks [l] + (filter #(= (:Type %) "Common Stock") l)) + +(defn save-list [exchange assets] + (->> assets + (filter-stocks) + (map convert-one) + (pr-str) + (spit (str "resources/symbollist/eodhd-" exchange ".edn")))) + +(save-list "AU" t) + + + + + + + + + + + diff --git a/lib/db/resources/quanta/notebook/asset_symbollist.clj b/lib/db/resources/quanta/notebook/asset_symbollist.clj new file mode 100644 index 00000000..9a50fdbe --- /dev/null +++ b/lib/db/resources/quanta/notebook/asset_symbollist.clj @@ -0,0 +1,52 @@ +(ns quanta.notebook.asset-symbollist + (:require + [ta.db.asset.db :as db] + [ta.db.asset.symbollist :refer [load-lists-full]] + [ta.import.provider.kibot-http.assets :as kibot-http])) + +(def asset-lists + [;crypto + "crypto" + "bybit" ; auto-generated from bybit + ; currency + "currency-spot" + ; futures + "futures-kibot" + ; bonds + "bonds" + ; mutualfunds + "fidelity-select" + ; etf + "commodity-industry" + "commodity-sector" + "equity-region" + "equity-region-country" + "equity-sector-industry" + "equity-style" + ; stocks + "eodhd-AU" + "test"]) + +(def asset-list-directory "resources/symbollist/") + +(def asset-lists-filenames + (map #(str asset-list-directory % ".edn") asset-lists)) + +(defn add-lists-to-db [filenames] + (let [asset-detail-seq (load-lists-full filenames)] + (doall (map db/add asset-detail-seq)))) + +(defn add-assets [] + (add-lists-to-db asset-lists-filenames) + (kibot-http/import-kibot-links "resources/kibot-http/" "forex") + (kibot-http/import-kibot-links "resources/kibot-http/" "futures") + (kibot-http/import-kibot-links "resources/kibot-http/" "etf") + (kibot-http/import-kibot-links "resources/kibot-http/" "stocks") + :assets-added-to-db) + +(comment + asset-lists-filenames + (add-assets) + +; + ) diff --git a/lib/db/resources/quanta/notebook/bardb_compress.clj b/lib/db/resources/quanta/notebook/bardb_compress.clj new file mode 100644 index 00000000..a223e793 --- /dev/null +++ b/lib/db/resources/quanta/notebook/bardb_compress.clj @@ -0,0 +1,25 @@ +(ns quanta.notebook.bardb-compress + (:require + [tick.core :as t] + [tablecloth.api :as tc] + [modular.system] + [ta.db.bars.protocol :as b])) + +(def db (modular.system/system :bardb-dynamic-compressing)) + +db + +(def window {:start (-> "1999-02-01T20:00:00Z" t/instant) + :end (-> "2001-03-01T20:00:00Z" t/instant)}) + +window + +; get all data available +(b/get-bars db + {:asset "MSFT" + :calendar [:us :month] + :import :kibot} + window) + + + diff --git a/lib/db/resources/quanta/notebook/bardb_duck.clj b/lib/db/resources/quanta/notebook/bardb_duck.clj new file mode 100644 index 00000000..ef731c12 --- /dev/null +++ b/lib/db/resources/quanta/notebook/bardb_duck.clj @@ -0,0 +1,57 @@ +(ns quanta.notebook.bardb-duck + (:require + [tick.core :as t] + [tablecloth.api :as tc] + [ta.db.bars.protocol :as b] + [ta.db.bars.duckdb :as duck] + [modular.system])) + +(def db (modular.system/system :duckdb)) +;(def db (modular.system/system :bardb-dynamic)) + +(def window {:start (t/instant "2022-03-05T00:00:00Z") + :end (t/instant "2024-03-20T20:00:00Z")}) + +(b/get-bars db + {:asset "USD/JPY" + :calendar [:forex :d] + ;:import :kibot + } + window) + +; daily: 2024-03-14T20:30:00Z +; minute: 2024-03-15T16:14:00Z + +(b/get-bars db + {:asset "UUP" + :calendar [:us :d] + :import :kibot} + window) + +; test for unknown asset +(b/get-bars db + {:asset "AEE.AU" + :calendar [:us :d] + :import :kibot} + window) + +(duck/delete-bars db [:us :d] "AEE.AU") + +(b/get-bars db {:asset "USD/JPY" + :calendar [:us :m]} + window) + +(-> (b/get-bars db {:asset "BTCUSDT" + ;:import :bybit + :calendar [:crypto :d]} + window) + (tc/select-columns [:date :close :volume :epoch :ticks])) + +(b/get-bars db + {:asset "EUR/USD" + :calendar [:us :d] + :import :kibot} + {:start (t/instant "2024-02-29T05:00:00Z") + :end (t/instant "2024-03-01T05:00:00Z")}) +{:type "forex", :symbol "EURUSD", :startdate "2024-02-29", :enddate "2024-03-01", + :interval "daily", :timezone "UTC", :splitadjusted 1} \ No newline at end of file diff --git a/lib/db/resources/quanta/notebook/bardb_duck_test.clj b/lib/db/resources/quanta/notebook/bardb_duck_test.clj new file mode 100644 index 00000000..b85bae93 --- /dev/null +++ b/lib/db/resources/quanta/notebook/bardb_duck_test.clj @@ -0,0 +1,92 @@ +(ns quanta.notebook.bardb-duck-test + (:require + [tick.core :as t] + [tablecloth.api :as tc] + [modular.system] + [ta.calendar.core :as cal] + [ta.db.bars.protocol :as b] + [ta.db.bars.duckdb :as duck] + [ta.db.bars.dynamic :as dynamic])) + +;; Test if duckdb get/append works + +(def db-duck (duck/start-bardb-duck "/tmp/demo12.ddb")) +db-duck +(duck/init-tables db-duck) + +(def ds + (tc/dataset [{:date (-> "1999-12-31T00:00:00Z" t/instant) + :open 1.0 :high 1.0 :low 1.0 :close 1.0 :volume 1.0} + {:date (-> "2000-12-31T00:00:00Z" t/instant) + :open 1.0 :high 1.0 :low 1.0 :close 1.0 :volume 1.0}])) +ds + +(duck/order-columns (duck/empty-ds [:us :d])) + +(b/append-bars db-duck {:asset "QQQ" + :calendar [:us :d] + :import :kibot} + (duck/empty-ds [:us :d])) + +(b/append-bars db-duck {:asset "QQQ" + :calendar [:us :d] + :import :kibot} + (duck/order-columns-strange (duck/empty-ds [:us :d]))) + +(b/append-bars db-duck {:asset "MSFT" + :calendar [:us :d] + :import :kibot} + ds) + +(def window {:start (-> "1999-02-01T20:00:00Z" t/instant) + :end (-> "2001-03-01T20:00:00Z" t/instant)}) +window + +; get all data available +(b/get-bars db-duck + {:asset "MSFT" + :calendar [:us :d] + :import :kibot} + {}) + +; just get the window +(b/get-bars db-duck + {:asset "MSFT" + :calendar [:us :d] + :import :kibot} + window) + +;; Test if DYAMIC get/append works + +(def db-dynamic (dynamic/start-bardb-dynamic db-duck "/tmp/overview")) +db-dynamic + +(defn window-as-date-time [window] + {:start (t/date-time (:start window)) + :end (t/date-time (:end window))}) + +(def window (-> (cal/trailing-range [:us :d] 10) + (window-as-date-time))) + +window + +(b/append-bars db-dynamic {:asset "MSFT" + :calendar [:us :d] + :import :kibot} ds) + +(-> (duck/empty-ds [:us :d]) (tc/info)) + +; since we dont have this asset in our db, it will fetch via kibot +; and save to duckdb. +(b/get-bars db-dynamic + {:asset "MSFT" + :calendar [:us :d] + :import :kibot} + window) + +;; check if we get the same number of bars back: +(b/get-bars db-duck + {:asset "QQQ" + :calendar [:us :d] + :import :kibot} + window) \ No newline at end of file diff --git a/lib/db/resources/quanta/notebook/bardb_dynamic.clj b/lib/db/resources/quanta/notebook/bardb_dynamic.clj new file mode 100644 index 00000000..38f2b4cd --- /dev/null +++ b/lib/db/resources/quanta/notebook/bardb_dynamic.clj @@ -0,0 +1,25 @@ +(ns quanta.notebook.bardb-dynamic + (:require + [tick.core :as t] + [modular.system] + [ta.calendar.core :as cal] + [ta.db.bars.protocol :as b])) + +(def db (modular.system/system :bardb-dynamic)) + +(def window (cal/trailing-range [:us :d] 10)) + +window + +(b/get-bars db + {:asset "QQQ" + :calendar [:us :d] + :import :kibot} + window) + +(b/get-bars db + {:asset "BTCUSDT" + :calendar [:crypto :d] + :import :bybit} + {:start (t/instant "2021-01-01T00:00:00Z") + :end (t/instant "2021-12-31T00:00:00Z")}) diff --git a/lib/db/resources/quanta/notebook/bardb_init.clj b/lib/db/resources/quanta/notebook/bardb_init.clj new file mode 100644 index 00000000..92d9ecf2 --- /dev/null +++ b/lib/db/resources/quanta/notebook/bardb_init.clj @@ -0,0 +1,53 @@ +(ns quanta.notebook.bardb-init + (:require + [tick.core :as t] + [tablecloth.api :as tc] + [ta.db.bars.protocol :as b] + [ta.db.bars.duckdb :as duck] + [modular.system])) + +(def db (modular.system/system :duckdb)) + +(duck/create-table db [:forex :d]) +(duck/create-table db [:forex :m]) + +(duck/create-table db [:crypto :d]) +(duck/create-table db [:crypto :m]) + +(duck/create-table db [:forex :month]) +(duck/create-table db [:us :month]) +(duck/create-table db [:crypto :month]) + +(def bar-ds + (-> {:date [(t/instant "2022-03-05T00:00:00Z") + (t/instant "2023-03-06T20:00:00Z") + (t/instant "2024-03-06T20:00:00Z")] + :open [10.0 20.0 30.0] + :high [10.0 20.0 30.0] + :low [10.0 20.0 30.0] + :close [10.0 20.0 30.0] + :volume [10.0 20.0 30.0] + :asset "XXX"} + tc/dataset)) + +bar-ds + +(b/append-bars db {:asset "XXX" + :calendar [:us :d]} + bar-ds) + +(b/get-bars db {:asset "XXX" + :calendar [:us :d]} + {:start (t/instant "2022-03-05T00:00:00Z") + :end (t/instant "2025-03-06T20:00:00Z")}) + +(b/get-bars db {:asset "EUR/USD" + :calendar [:forex :d]} + {:start (t/instant "2022-03-05T00:00:00Z") + :end (t/instant "2025-03-06T20:00:00Z")}) + +(b/get-bars db {:asset "EUR/USD" + :calendar [:forex :d]} + {:start (t/zoned-date-time "2024-03-07T16:30-05:00[America/New_York]") + :end (t/zoned-date-time "2020-05-08T16:30-04:00[America/New_York]")}) + diff --git a/lib/db/resources/quanta/notebook/bardb_load.clj b/lib/db/resources/quanta/notebook/bardb_load.clj new file mode 100644 index 00000000..f174a4d9 --- /dev/null +++ b/lib/db/resources/quanta/notebook/bardb_load.clj @@ -0,0 +1,36 @@ +(ns quanta.notebook.bardb-load + (:require + [tick.core :as t] + [tablecloth.api :as tc] + [ta.db.bars.protocol :as b] + [ta.db.bars.nippy :as nippy] + [modular.system])) + +(def db (nippy/start-bardb-nippy "output/kibot-intraday/")) + +(def window {:start (t/instant "2022-03-05T00:00:00Z") + :end (t/instant "2024-03-20T20:00:00Z")}) + +(b/get-bars db + {:asset "JY0" + :calendar [:forex :m]} + window) + +(b/get-bars db + {:asset "EUR/USD" + :calendar [:forex :m]} + window) + +(b/get-bars db + {:asset "USD/JPY" + :calendar [:forex :d]} + window) + +(-> (b/get-bars db + {:asset "QQQ" ; "USD/JPY" + :calendar [:forex :m]} + window)) + +;; 2024-03-15T14:17-04:00[America/New_York] etf 30 MIN DELAYED. +;; 2024-03-15T12:14-04:00[America/New_York] forex (seems to be UK close) +;; 2024-03-15T03:22-04:00[America/New_York] future (seems to be tokyo close) diff --git a/lib/db/resources/quanta/notebook/bardb_performance_test.clj b/lib/db/resources/quanta/notebook/bardb_performance_test.clj new file mode 100644 index 00000000..fa3a7f2b --- /dev/null +++ b/lib/db/resources/quanta/notebook/bardb_performance_test.clj @@ -0,0 +1,294 @@ +(ns quanta.notebook.bardb-performance-test + (:require + [taoensso.timbre :refer [trace debug info warn error]] + [clojure.string :as str] + [tick.core :as t] + [tmducken.duckdb :as duckdb] + [tech.v3.dataset :as ds] + [clojure.java.io :as java-io] + [ta.db.bars.protocol :refer [bardb barsource]] + [ta.db.bars.protocol :as b] + [ta.db.bars.duckdb :refer [start-bardb-duck stop-bardb-duck]] + [ta.calendar.calendars :refer [calendars]] + [ta.calendar.core :as cal] + [ta.algo.env :as algo-env-impl] + [ta.algo.env.protocol :as algo-env] + ;[ta.algo.backtest :refer [run-backtest]] + [ta.engine.protocol :as eng] + [ta.calendar.combined :refer [combined-event-seq]])) + +(defn- duckdb-start [db-filename] + (duckdb/initialize! {:duckdb-home "../../app/demo/binaries"}) + (let [db (duckdb/open-db db-filename) + conn (duckdb/connect db)] + {:db db + :conn conn})) + +;; RANDOM CANDLE + +(defn vec->sql-str [arr] + (str "[" (str/join ", " (map #(str "'" % "'") arr)) "]")) + +(defn gen-asset-names + ([n] + (gen-asset-names 1 n)) + ([from n] + (map #(str "ASSET_" %) (range from (inc n))))) + +(defn create-partition-table [conn table-name from to] + (duckdb/run-query! conn + (format "CREATE TABLE %s PARTITION OF %s + FOR VALUES FROM ('%s') TO ('%s');", + (str table-name "_" from) + table-name + from + to))) + +(defn create-ohcl-table [conn table-name] + (duckdb/run-query! conn + (format "CREATE TABLE %s ( + date TIMESTAMP, + open DOUBLE, + high DOUBLE, + low DOUBLE, + close DOUBLE, + volume DOUBLE, + ticks BIGINT, + epoch BIGINT, + asset VARCHAR);", table-name))) + +(defn insert-random-candles [conn table-name from to assets] + (duckdb/run-query! conn (format + "INSERT INTO %s (date, open, high, low, close, volume, ticks, epoch, asset) + SELECT date, + round(random() * 1000) AS open, + round(random() * 1000) AS high, + round(random() * 1000) AS low, + round(random() * 1000) AS close, + round(random() * 1000) AS volume, + round(random() * 10) AS ticks, + round(random() * 10) AS epoch, + (%s)[i] as asset + FROM generate_series(TIMESTAMP '%s', TIMESTAMP '%s', INTERVAL 1 MINUTE) AS t1(date), + generate_series(1,%d) AS t2(i), + ORDER BY date;", table-name (vec->sql-str assets) from to (count assets)))) + +(defn get-total-count [conn table-name] + (-> (duckdb/sql->dataset conn (format "select count(*) from %s", table-name)) (first) (second) (first))) + +(defn measure-insert [conn table-name from to assets] + (println "ingesting..." from "-" to ", " (first assets) "-" (last assets)) + (time (insert-random-candles conn table-name from to assets)) + (println "total rows: " (get-total-count conn table-name)) + (println "-------------------------------------------------------------------------------")) + +(defn get-range-start-dt [to-year n] + (let [from-year (- to-year (dec n))] + (str from-year "-01-01 00:00:00"))) + +(defn generate-year-ranges [start-year end-year] + (for [year (range start-year (inc end-year))] + [(str year "-01-01 00:00:00") (str year "-12-31 23:59:00")])) + +(defn create-new-db [path {:keys [years assets]} [calendar-kw interval-kw] & [db-state]] + (let [table-name (str (name calendar-kw) "_" (name interval-kw)) + path (str path "/duckdb-partitioning_" table-name "_" assets "a_" years "y.db") + {:keys [db conn new?] :as state} (if db-state + db-state + (start-bardb-duck path)) + to-year 2023 + from-year (- to-year (dec years)) + year-ranges (generate-year-ranges from-year to-year)] + (create-ohcl-table conn table-name) + (doseq [[from to] year-ranges] + (doseq [asset-range (partition-all 10 (range 1 (inc assets)))] + (measure-insert conn + table-name + from + to + (gen-asset-names (first asset-range) (last asset-range))))) + (if (not db-state) + (stop-bardb-duck state)))) + +(defn create-hive-partition-by-year [conn table-name path] + (duckdb/run-query! conn + (str "COPY (select *, EXTRACT(YEAR FROM date) AS year + from " table-name ") + TO '" path "' (FORMAT PARQUET, PARTITION_BY (year));"))) + +(defn create-hive-partition-by-asset [conn table-name path] + (duckdb/run-query! conn + (str "COPY " table-name " + TO '" path "' (FORMAT PARQUET, PARTITION_BY (asset));"))) + +(defn trailing-window-test [db start end] + ;(loop [cur (cal/current-close :crypto :m end)] + ; (if (t/>= cur start) + (let [table-name "crypto_m" + asset "ASSET_1" + ;dstart (str (t/date cur) + ; " " + ; (t/time cur)":00") + ;dend dstart + dstart (str (t/date start) + " " + (t/time start) ":00") + dend (str (t/date end) + " " + (t/time end) ":00") + query (str "select * from " table-name + " where asset = '" asset "'" + ;" and date = '" dstart "'" + ;" and date >= '" dstart "'" + ;" and date <= '" dend "'" + " order by date") + res (duckdb/sql->dataset (:conn db) query)] + (println res) + ;(b/get-bars db {:asset "ASSET_1" :calendar [:crypto :m]} {:start (t/instant "2023-01-01T00:00:00Z") + ; :end (t/instant "2023-01-01T00:10:00Z")}) + ;(recur (cal/prior-close :crypto :m cur)) + )) +;)) + +(defn secret [env spec time] + (str "the spec is: " spec " (calculated: " time ")")) + +(def spec {:type :trailing-bar + :calendar [:crypto :m] + :data 42 + :asset "ASSET_1" + :trailing-n 500000 + :algo 'notebook.playground.bardb.performance-test/secret}) + +(defn run-backtest [env window] + (let [engine (algo-env/get-engine env) + cals (eng/active-calendars engine) + event-seq (combined-event-seq window cals)] + (info "backtesting window: " window " ..") + (doall (map #(eng/set-calendar! engine %) event-seq)) + (info "backtesting window: " window "finished!") + :backtest-finished)) + +(defn backtest-algo + "run a single bar-strategy with data powered by bar-db-kw. + returns the result of the strategy." + [bar-db algo-spec dt] + (let [env (algo-env-impl/create-env-javelin bar-db) + strategy (algo-env/add-algo env algo-spec) + calendar [:us :m] + window (cal/trailing-range calendar 1 dt)] + (run-backtest env window) + strategy)) + +(defn backtest-algo-date + "run a single bar-strategy with data powered by bar-db-kw + as of date dt. returns the result of the strategy." + [bar-db algo-spec dt] + (let [;bar-db (modular.system/system bar-db-kw) + env (algo-env-impl/create-env-javelin bar-db) + strategy (algo-env/add-algo env algo-spec) + engine (algo-env/get-engine env) + calendars (eng/active-calendars engine) + prior-dates (map (fn [[calendar-kw interval-kw]] + (cal/current-close calendar-kw interval-kw dt)) + calendars) + ;prior-dates-sorted (sort prior-dates) + event-seq (map (fn [cal dt] + {:calendar cal :time dt}) calendars prior-dates)] + (info "event-seq: " event-seq) + (doall (map #(eng/set-calendar! engine %) event-seq)) + strategy)) + +(defn- exists-db? [path] + (.exists (java-io/file path))) + +(defn single-test [{:keys [years assets]}] + (println "===========================================================") + (println "years: " years "assets: " assets) + (println "===========================================================") + (let [db-name (str "duckdb-partitioning_crypto_m_" assets "a_" years "y.db") + base-dir "/tmp" + path (str base-dir "/" db-name) + exists? (exists-db? path) + db (start-bardb-duck path) + trailing-n (* 500000 years)] + + ; create database + (if (not exists?) + (create-new-db base-dir {:assets assets :years years} [:crypto :m] db)) + + ;; Backtest + (time (backtest-algo db (assoc spec :trailing-n trailing-n) (t/in (t/date-time "2023-12-31T23:59:00") "America/New_York"))) + ;(time (backtest-algo-date db (assoc spec :trailing-n trailing-n) (t/in (t/date-time "2023-12-31T23:59:00") "America/New_York"))) + + ; simple read all candles from db + ;(time (trailing-window-test db + ; (t/in (t/date-time "1924-01-01T00:00:00") "America/New_York") + ; (t/in (t/date-time "2023-12-29T23:59:00") "America/New_York"))) + (stop-bardb-duck db))) + +(defn run-performance-test [_] + (single-test {:years 1 :assets 1}) + (single-test {:years 10 :assets 1}) + (single-test {:years 100 :assets 1})) + +(comment + (def base-path "~/Desktop/tmp") + + ; create databases + (create-new-db base-path {:assets 1 :years 1} [:crypto :m]) ; 12 MB + (create-new-db base-path {:assets 100 :years 10} [:crypto :m]) ; 11 GB + + (create-new-db base-path {:assets 1 :years 10} [:crypto :m]) ; 110 MB + (create-new-db base-path {:assets 1 :years 100} [:crypto :m]) ; 1.1 GB + + (create-new-db base-path {:assets 10 :years 1} [:crypto :m]) ; 114 MB + (create-new-db base-path {:assets 100 :years 1} [:crypto :m]) ; 1.1 GB + (create-new-db base-path {:assets 1000 :years 1} [:crypto :m]) ; 11 GB + + ;(def duckdb (:duckdb modular.system/system)) + ;(def db (modular.system/system :duckdb)) + + ; init db + (require '[ta.db.bars.duckdb :refer [start-bardb-duck]]) + (def db-name "duckdb-partitioning_crypto_m_1a_100y.db") + (def db-path "~/Desktop/tmp") + (def hive-path "~/Desktop/tmp/hive") + (def db (start-bardb-duck (str db-path "/" db-name))) + + ; partitioning + ;(create-partition-table (:conn db) "crypto_m" "2023-01-01T00:00:00" "2023-12-31T23:59:00") + ;(create-hive-partition-by-year (:conn db) "crypto_m" (str hive-path"/"db-name)) + + ; get window + ;(require '[ta.db.bars.protocol :as b]) + ;(b/get-bars db {:asset "ASSET_1" :calendar [:crypto :m]} {:start (t/instant "2023-01-01T00:00:00Z") :end (t/instant "2023-01-01T00:10:00Z")}) + + ;; Backtest + (time (backtest-algo db (assoc spec :trailing-n 50000000) (t/in (t/date-time "2023-12-31T23:59:00") "America/New_York"))) + ;(time (backtest-algo-date db (assoc spec :trailing-n 50000000) (t/in (t/date-time "2023-12-31T23:59:00") "America/New_York"))) + ;(time (trailing-window-test db + ; (t/in (t/date-time "1924-01-01T00:00:00") "America/New_York") + ; (t/in (t/date-time "2023-12-29T23:59:00") "America/New_York") ; last trading day in 2023 + ; )) + + ;; roundtrip + ; TODO + ;(require '[ta.trade.signal :refer [trade-signal]]) + ;(require '[ta.trade.roundtrip-backtest :refer [calc-roundtrips]]) + ;(trade-signal ds-demo) + ; + ;(-> (trade-signal ds-demo) + ; (calc-roundtrips {}) + ; ) + ; + ;(trade-signal ds-bars) + + ;; results + ; 500k bars x 1 asset 1y = 1.628 | 2.597 sec + ; 500k bars x 10 asset 1y = 1.5 | 1.7 sec + ; 500k bars x 1000 asset 1y = 2.0 | 2.3 | 3.2 sec + + ; 5mio bars x 1 asset 10y = 16.71 sec + ; 50mio bars x 1 asset 100y = 274.860 sec + ) \ No newline at end of file diff --git a/lib/engine/deps.edn b/lib/engine/deps.edn index 0a6d6279..5884fc08 100644 --- a/lib/engine/deps.edn +++ b/lib/engine/deps.edn @@ -1,4 +1,4 @@ -{:paths ["src"] +{:paths ["src" "resources"] :deps {org.clojure/clojure {:mvn/version "1.11.1"} hoplon/javelin {:mvn/version "3.9.3"}} diff --git a/lib/engine/resources/quanta/notebook/engine_direct.clj b/lib/engine/resources/quanta/notebook/engine_direct.clj new file mode 100644 index 00000000..19768883 --- /dev/null +++ b/lib/engine/resources/quanta/notebook/engine_direct.clj @@ -0,0 +1,26 @@ +(ns quanta.notebook.engine-direct + (:require + [ta.engine.javelin :refer [create-engine-javelin]] + [ta.engine.protocol :as p])) + +(def e (create-engine-javelin)) + +(def c (p/value-cell e 15)) +@c + +(def t (p/calendar-cell e identity [:us :d])) +@t + +(p/set-calendar! e {:calendar [:us :d] :time :sometime-later}) +@t + +(defn fun [c] (* c 1000)) + +(def x (p/formula-cell e fun [c])) + +@x + +(reset! c 5) +@c + +@x \ No newline at end of file diff --git a/lib/engine/resources/quanta/notebook/engine_javelin.clj b/lib/engine/resources/quanta/notebook/engine_javelin.clj new file mode 100644 index 00000000..88c9546b --- /dev/null +++ b/lib/engine/resources/quanta/notebook/engine_javelin.clj @@ -0,0 +1,21 @@ +(ns quanta.notebook.engine.javelin + (:require + [javelin.core-clj :refer [cell cell=]])) + +(defn start [] + (let [a (cell 0) ;; input cell with initial value of 0. + b (cell= (inc a)) ;; formula cell of a+1. + c (cell= (+ 123 a b))] ;; formula cell of a+b+123. + (cell= (println c)) ;; anonymous formula cell for side effects. + ;; c's initial value, 124, is printed. + (swap! a inc) + ;; a was incremented, and its new value propagated (consistently) + ;; through b and c. c's new value, 126, is printed to the console. + :done)) + +(start) + +; prints: +; 124 +; 126 +; :done \ No newline at end of file diff --git a/lib/engine/resources/quanta/notebook/engine_ops.clj b/lib/engine/resources/quanta/notebook/engine_ops.clj new file mode 100644 index 00000000..7bb50b2c --- /dev/null +++ b/lib/engine/resources/quanta/notebook/engine_ops.clj @@ -0,0 +1,42 @@ +(ns quanta.notebook.engine-ops + (:require + [ta.engine.javelin :refer [create-engine-javelin]] + [ta.engine.ops :refer [add-ops]] + [ta.engine.protocol :as p])) + +(def e (create-engine-javelin)) + +(defn time-as-map [t] {:time t}) + +(def ops-1 + [[0 {:calendar [:us :d] :time-fn time-as-map}]]) + +(def c (add-ops e ops-1)) +c +@c + +(p/set-calendar! e {:calendar [:us :d] + :time :much-later}) + +@c + +(def ops-multiple + [[0 {:calendar [:us :d] :time-fn time-as-map}] + [1 {:calendar [:us :h] :time-fn time-as-map}] + [2 {:formula [0 1] :formula-fn concat}] + [3 {:value 27}] + [4 {:formula [3] :formula-fn inc}] + [5 {:formula [3 4] :formula-fn +}]]) + +(def cells (add-ops e ops-multiple)) + +cells +(get cells 0) + +(def c (get cells 3)) +@c +(reset! c 100) +@c + +(def d (get cells 4)) +@d \ No newline at end of file diff --git a/lib/import/deps.edn b/lib/import/deps.edn index dde0b12b..a970ada2 100644 --- a/lib/import/deps.edn +++ b/lib/import/deps.edn @@ -1,4 +1,4 @@ -{:paths ["src"] +{:paths ["src" "resources"] :deps {org.clojure/clojure {:mvn/version "1.11.1"} org.clojure/core.async {:mvn/version "1.3.618"} clj-http/clj-http {:mvn/version "3.12.3"} ; http requests (bybit) diff --git a/lib/import/resources/quanta/notebook/import_alphavantage.clj b/lib/import/resources/quanta/notebook/import_alphavantage.clj new file mode 100644 index 00000000..b3382564 --- /dev/null +++ b/lib/import/resources/quanta/notebook/import_alphavantage.clj @@ -0,0 +1,45 @@ +(ns quanta.notebook.import-alphavantage + (:require + [clojure.pprint :refer [print-table]] + [ta.data.alphavantage :as av])) + +; select search +(av/search "S&P 500") +(print-table [:symbol :type :name] (av/search "BA")) +(print-table (av/search "Fidelity MSCI")) + +(av/search "gld") + +;; # stock series +(av/get-daily :compact "QQQ") +(print-table (->> (av/get-daily :full "MSFT") + :series + ;reverse + (take 5))) + +(-> + (av/get-daily-adjusted :compact "QQQ") + :series + ;first + last) + +(print-table (->> (av/get-daily-adjusted :full "MSFT") + :series + ;reverse + (take 5))) + +;; # fx series +(print-table (take 5 (reverse (av/get-daily-fx :compact "EURUSD")))) + +;; # crypto series +(print-table (take 5 (reverse (av/get-daily-crypto :compact "BTC")))) + +; crypto rating +(av/get-crypto-rating "BTC") + +(print-table + (map av/get-crypto-rating ["BTC" "ETH" "LTC" "DASH" + "NANO" "EOS" "XLM"])) + + + diff --git a/lib/import/resources/quanta/notebook/import_bardb_dynamic.clj b/lib/import/resources/quanta/notebook/import_bardb_dynamic.clj new file mode 100644 index 00000000..c05ef5fd --- /dev/null +++ b/lib/import/resources/quanta/notebook/import_bardb_dynamic.clj @@ -0,0 +1,24 @@ +(ns quanta.notebook.import-bardb-dynamic + (:require + [taoensso.timbre :refer [info warn error]] + [tick.core :as t] + [modular.system] + [ta.calendar.core :as cal] + [ta.db.bars.protocol :as b])) + +(def db (modular.system/system :bardb-dynamic)) + +(def window-daily + (cal/trailing-range [:us :d] 200 + (t/zoned-date-time "2024-03-07T17:30-05:00[America/New_York]"))) + +window-daily + +(defn get-eodhd-daily [asset] + (info "getting eodhd data for: " asset) + (b/get-bars db {:asset asset + :calendar [:us :d] + :import :eodhd} + window-daily)) + +(get-eodhd-daily "AEE.AU") diff --git a/lib/import/resources/quanta/notebook/import_kibot_intraday.clj b/lib/import/resources/quanta/notebook/import_kibot_intraday.clj new file mode 100644 index 00000000..c7fe7904 --- /dev/null +++ b/lib/import/resources/quanta/notebook/import_kibot_intraday.clj @@ -0,0 +1,63 @@ +(ns quanta.notebook.import-kibot-intraday + (:require + [tick.core :as t] + [taoensso.timbre :as timbre :refer [debug info warn error]] + [tablecloth.api :as tc] + [ta.db.bars.protocol :as b] + [ta.db.bars.nippy :as nippy] + [ta.import.helper.retries :refer [with-retries]] + [modular.system] + [de.otto.nom.core :as nom])) + +(def im (modular.system/system :import-manager)) + +im + +(def db (nippy/start-bardb-nippy "output/kibot-intraday/")) + +db +(nippy/filename-asset db {:asset "EUR/USD" + :calendar [:forex :m]}) + +(defn import-asset [asset] + (let [opts {:asset asset + :calendar [:forex :m] + :import :kibot-http} + ds (with-retries 5 b/get-bars im opts + {:start (t/instant "2019-12-01T00:00:00Z") + :end (t/instant "2020-02-01T00:00:00Z")})] + (if (nom/anomaly? ds) + (do + (error "could not get asset: " asset) + {:asset asset :count 0}) + (let [c (tc/row-count ds)] + (info "recevied from kibot asset:" asset " count: " c) + (b/append-bars db opts ds) + {:asset asset :count c})))) + +(defn import-assets [assets] + (let [r (doall (map import-asset assets))] + (spit "output/kibot-intraday/summary.edn" (pr-str r)))) + +(import-asset "USD/JPY") + +(import-assets ["EUR/USD" "USD/CHF" "GBP/USD" "USD/SEK" + "USD/NOK" "USD/CAD" "USD/JPY" "AUD/USD" + "NZD/USD" "USD/MXN" "USD/ZAR" "EUR/JPY" + "EUR/CHF" "EUR/GBP" "GBP/JPY"]) + +(import-assets ["EU0" "SF0" "BP0" "SEK0" "NOK0" + "CD0" "JY0" "AD0" "NE0" "PX0" + "RA0" "RY0" "RF0" "RP0" "PJY0"]) + +(import-assets ["SPY" "QQQ"]) + +(import-assets ["JY0" "USD/JPY"]) + +(import-assets ["EU0" "SF0" "BP0"]) + +(import-assets ["INTC"]) + + + + diff --git a/lib/import/resources/quanta/notebook/import_manager.clj b/lib/import/resources/quanta/notebook/import_manager.clj new file mode 100644 index 00000000..24dbadea --- /dev/null +++ b/lib/import/resources/quanta/notebook/import_manager.clj @@ -0,0 +1,68 @@ +(ns quanta.notebook.import-manager + (:require + [tick.core :as t] + [ta.db.bars.protocol :as b] + [modular.system])) + +(def im (modular.system/system :import-manager)) + +im + +(def dt (t/instant "2024-02-01T00:00:00Z")) +dt + +;; BYBIT +(b/get-bars im {:asset "BTCUSDT" ; crypto + :calendar [:crypto :d] + :import :bybit} + {:start (t/instant "2020-01-01T00:00:00Z") + :end (t/instant "2024-01-01T00:00:00Z")}) + +;; ALPHAVANTAGE +(b/get-bars im {:asset "FMCDX" ; mutual fund + :calendar [:us :d] + :import :alphavantage} + {:start dt + :mode :append}) + +(defn date-type [ds] + (-> ds :date meta :datatype)) + +;; KIBOT +(-> (b/get-bars im {:asset "NG0" ; future + :calendar [:us :d] + :import :kibot} + {:start (t/instant "2020-01-01T00:00:00Z") + :end (t/instant "2024-01-01T00:00:00Z")}) + date-type) + +(b/get-bars im + {:asset "EUR/USD" ; forex + :calendar [:forex :d] + :import :kibot} + {:start (t/instant "2023-09-01T00:00:00Z") + :end (t/instant "2024-05-01T00:00:00Z")}) + +(b/get-bars im {:asset "EU0" ; future(forex) + :calendar [:us :d] + :import :kibot} + {:start (t/instant "2023-09-01T00:00:00Z") + :end (t/instant "2023-10-01T00:00:00Z")}) + +(b/get-bars im + {:asset "MSFT" + :calendar [:us :d] + :import :kibot} + {:start (t/instant "2019-12-01T00:00:00Z") + :end (t/instant "2020-02-01T00:00:00Z")}) + +; eodhd + +(b/get-bars im + {:asset "AEE.AU" + :calendar [:us :d] + :import :eodhd} + ; fails because more than a year ago + {:start (-> "2023-12-01T00:00:00Z" t/instant) + :end (-> "2024-04-01T00:00:00Z" t/instant)}) + diff --git a/lib/import/resources/quanta/notebook/import_quandl.clj b/lib/import/resources/quanta/notebook/import_quandl.clj new file mode 100644 index 00000000..556e9f4a --- /dev/null +++ b/lib/import/resources/quanta/notebook/import_quandl.clj @@ -0,0 +1,61 @@ +(ns quanta.notebook.import-quandl + (:require + [tablecloth.api :as tc] + [ta.warehouse :as wh] + [ta.warehouse.since-importer :as since-importer] + [ta.data.quandl :as quandl] + [ta.helper.date :refer [parse-date]])) + +(defn quandl-result->ds [{:keys [data columns]}] + (-> (tc/dataset data {:column-names columns}) + (tc/rename-columns {"Date" :date + "Open" :open + "High" :high + "Low" :low + "Settle" :close + "Volume" :volume + "Prev. Day Open Interest" :open-interest-1}) + (tc/convert-types :date [[:local-date-time parse-date]]))) + +(defn quandl-get-since-ds [_frequency _since symbol] + (let [quandl-result (quandl/cfuture-request symbol {})] + (quandl-result->ds quandl-result))) + +(def dax-full (quandl/cfuture-request "FDAX" {})) +(def dax-2023 (quandl/cfuture-request "FDAX" {:start_date "2021-06-25"})) + +(def gold-2023 (quandl/cfuture-request "GC" {:start_date "2021-01-01"})) + +(quandl/quandl-metadata "CHRIS/EUREX_FDAX1" {}) + +(quandl/quandl-metadata "CHRIS/CME_GC1" {}) + +(quandl/quandl-metadata "SCF/CBOE_VX2N" {}) + +; WTI spot +(quandl/quandl-metadata "EIA/PET_RWTC_D" {}) + +gold-2023 + +quandl-result +quandl-result-2023 + +(quandl-result->ds quandl-result) + +;(quandl-get-since-ds "D" "2021-01-01" "FDAX") + +#_(defn get-alphavantage-daily [symbols] + (let [start-date-dummy nil] + (since-importer/init-symbols + :stocks alphavantage-get-since-ds "D" + start-date-dummy symbols))) + +; ********************************************************************************************+ +(comment + + (def symbols (wh/load-list "test")) + + ; (get-alphavantage-daily ["QQQ" "SPY" "TLT"]) + +; + ) \ No newline at end of file diff --git a/lib/interact/resources/quanta/notebook/interact.clj b/lib/interact/resources/quanta/notebook/interact.clj new file mode 100644 index 00000000..62e635f6 --- /dev/null +++ b/lib/interact/resources/quanta/notebook/interact.clj @@ -0,0 +1,78 @@ +(ns quanta.notebook.interact + (:require + [ta.interact.template :refer [get-options]] + [ta.interact.subscription :as sub])) + +(-> :watch-crypto get-options) + +(-> :juan-fx + get-options + ;:current + ) +;; => {:options +;; [{:path [0 :asset], +;; :name "asset", +;; :spec +;; ["EUR/USD" +;; "USD/CHF" +;; "GBP/USD" +;; "USD/SEK" +;; "USD/NOK" +;; "USD/CAD" +;; "USD/JPY" +;; "AUD/USD" +;; "NZD/USD" +;; "USD/MXN" +;; "USD/ZAR" +;; "EUR/JPY" +;; "EUR/CHF" +;; "EUR/GBP" +;; "GBP/JPY"]} +;; {:path [2 :trailing-n], :name "DailyLoad#", :spec [2 5 10 20 30 50 80 100 120 150]} +;; {:path [2 :atr-n], :name "dATR#", :spec [5 10 20 30]} +;; {:path [2 :percentile], :name "dPercentile", :spec [10 20 30 40 50 60 70 80 90]} +;; {:path [2 :step], :name "dStep", :spec [0.001 1.0E-4 4.0E-5]} +;; {:path [4 :max-open-close-over-low-high], :name "doji-co/lh max", :spec [0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9]}], +;; :current +;; {[0 :asset] "USD/JPY", +;; [2 :trailing-n] 120, +;; [2 :atr-n] 10, +;; [2 :percentile] 70, +;; [2 :step] 1.0E-4, +;; [4 :max-open-close-over-low-high] 0.3}} + +; subscribe +(def subscription-id + (sub/subscribe-live + :crypto-watch {:asset "ETHUSDT"})) + +subscription-id + +(def subscription-id "79zRE_") + +; check state (developer debugging) + +(-> @sub/subscriptions-a keys) +;; => ("c3ZNXs") + +;; => ("79zRE_") + +;; => ("YEoVgy") + +;; => ("x7u1cu") + +;; => () + +(-> @sub/results-a keys) +(-> @sub/visualizations-a keys) + +;; watch results.. +(def subscription-id "c3ZNXs") + +(-> @sub/subscriptions-a (get subscription-id)) +(-> @sub/results-a (get subscription-id)) +(-> @sub/visualizations-a (get subscription-id)) + +; (require '[algodemo.sentiment-spread.vega :refer [calc-viz-vega]]) +; (calc-viz-vega (-> @sub/results-a :sentiment-spread)) + diff --git a/lib/interact/resources/quanta/notebook/interact_debug.clj b/lib/interact/resources/quanta/notebook/interact_debug.clj new file mode 100644 index 00000000..09c5b45a --- /dev/null +++ b/lib/interact/resources/quanta/notebook/interact_debug.clj @@ -0,0 +1,162 @@ +(ns quanta.notebook.interact-debug + (:require + [tablecloth.api :as tc] + [tech.v3.dataset.print :refer [print-range]] + [ta.interact.template :refer [get-options]] + [ta.interact.subscription :as sub] + [ta.interact.debug :refer [dump-dataset]])) + +(defn get-sub [] + (let [active (-> @sub/subscriptions-a keys) + ;; => ("Z7FaM3" "huAQz9") + ] + (when (= 1 (count active)) + (first active)))) + +(-> @sub/subscriptions-a (get subscription-id)) +(-> @sub/results-a (get subscription-id)) +(-> @sub/visualizations-a (get subscription-id)) + +(defn get-result [] + (let [id (get-sub)] + (when id + (-> @sub/results-a (get id) deref)))) + +(get-result) + +(defn dump-ds [ds] + (dump-dataset "/tmp/test.txt" ds)) + +(-> (get-result) + (tc/select-columns [:date :close :high :b2-upper + :b2h-crossed? :b2h-cross-high + :carried-high :carried-crossed?]) + (print-range :all) + (dump-ds)) + +(defn get-viz [] + (let [id (get-sub)] + (when id + (-> @sub/visualizations-a (get id))))) + +(get-viz) + +(def v @(get-viz)) + +v + +(-> v keys) + +(:spec v) + ;; => {:ohlc-height 600, + ;; :boost false, + ;; :series + ;; [{:color "blue", + ;; :allowOverlapX true, + ;; :dataGrouping {:enabled false}, + ;; :name ":carried-crossed?", + ;; :type "flags", + ;; :yAxis 0, + ;; :id ":carried-crossed?", + ;; :shape "squarepin", + ;; :zIndex 9999, + ;; :fillColor "rgba(255, 255, 255, .4)", + ;; :onSeries ":close"} + ;; {:type "line", + ;; :id ":b1-upper", + ;; :name ":b1-upper", + ;; :yAxis 0, + ;; :zIndex 1000, + ;; :dataGrouping {:enabled false}, + ;; :color "black"} + ;; {:color "blue", + ;; :allowOverlapX true, + ;; :dataGrouping {:enabled false}, + ;; :name ":b2h-crossed?", + ;; :type "flags", + ;; :yAxis 0, + ;; :id ":b2h-crossed?", + ;; :shape "squarepin", + ;; :zIndex 9999, + ;; :fillColor "rgba(255, 255, 255, .4)", + ;; :onSeries ":close"} + ;; {:color "blue", + ;; :dataGrouping {:enabled false}, + ;; :name ":b1-mid", + ;; :marker {:enabled true, :radius 2}, + ;; :type "line", + ;; :yAxis 0, + ;; :id ":b1-mid", + ;; :lineWidth 0, + ;; :zIndex 1000} + ;; {:type "candlestick", + ;; :id ":close", + ;; :name ":close", + ;; :yAxis 0, + ;; :zIndex 1000, + ;; :dataGrouping {:enabled false}, + ;; :color "blue"} + ;; {:type "line", + ;; :id ":b2-lower", + ;; :name ":b2-lower", + ;; :yAxis 0, + ;; :zIndex 1000, + ;; :dataGrouping {:enabled false}, + ;; :color "red"} + ;; {:type "line", + ;; :id ":b2-upper", + ;; :name ":b2-upper", + ;; :yAxis 0, + ;; :zIndex 1000, + ;; :dataGrouping {:enabled false}, + ;; :color "red"} + ;; {:type "line", + ;; :id ":b1-lower", + ;; :name ":b1-lower", + ;; :yAxis 0, + ;; :zIndex 1000, + ;; :dataGrouping {:enabled false}, + ;; :color "black"} + ;; {:type "line", + ;; :id ":carried-high", + ;; :name ":carried-high", + ;; :yAxis 0, + ;; :zIndex 1000, + ;; :dataGrouping {:enabled false}, + ;; :color "blue", + ;; :step true} + ;; {:type "column", + ;; :id ":bars-above-b1h", + ;; :name ":bars-above-b1h", + ;; :yAxis 1, + ;; :zIndex 1000, + ;; :dataGrouping {:enabled false}, + ;; :color "blue"} + ;; {:type "column", + ;; :id ":volume", + ;; :name ":volume", + ;; :yAxis 2, + ;; :zIndex 1000, + ;; :dataGrouping {:enabled false}, + ;; :color "blue"}], + ;; :other-height 100, + ;; :box :fl, + ;; :rangeSelector false, + ;; :plotOptions {:series {:animation 0}}, + ;; :chart {:height 900}, + ;; :yAxis + ;; [{:resize {:enabled true}, :lineWidth 2, :labels {:align "right", :x -3}, :height 600, :title {:text "OHLC"}} + ;; {:resize {:enabled true}, :lineWidth 2, :labels {:align "right", :x -3}, :top 600, :height 100} + ;; {:resize {:enabled true}, :lineWidth 2, :labels {:align "right", :x -3}, :top 700, :height 100} + ;; {:resize {:enabled true}, :lineWidth 2, :labels {:align "right", :x -3}, :top 800, :height 100}], + ;; :credits {:enabled false}, + ;; :navigator false, + ;; :xAxis {:crosshair {:snap true}}, + ;; :tooltip {:style {:width "200px"}, :valueDecimals 4, :shared true}} + +(:data v) + +;{:x 1711227540000, :title "true", :shape "url(/r/arrow-down.svg)", :text "col: :carried-crossed?val: true"} + ;{:x 1711240080000, :title "false", :shape nil, :text "col: :carried-crossed?val: false"} + + \ No newline at end of file diff --git a/lib/math/deps.edn b/lib/math/deps.edn index 067f0ff4..13e904cd 100644 --- a/lib/math/deps.edn +++ b/lib/math/deps.edn @@ -1,4 +1,5 @@ -{:paths ["src"] +{:paths ["src" + "resources"] :deps {org.clojure/clojure {:mvn/version "1.11.1"} scicloj/tablecloth {:mvn/version "7.021"} ; brings techml-dataset com.stuartsierra/frequencies {:mvn/version "0.1.0"} ; percentile stats diff --git a/lib/math/resources/quanta/notebook/math_bin.clj b/lib/math/resources/quanta/notebook/math_bin.clj new file mode 100644 index 00000000..7c403bbe --- /dev/null +++ b/lib/math/resources/quanta/notebook/math_bin.clj @@ -0,0 +1,44 @@ +(ns quanta.notebook.math-bin + (:require [ta.math.bin :refer [bin] :as b])) + + ; For example, we can bin range 0-14 into 5 bins like so: +(bin {:n 5} (range 15)) + ;; (0 0 0 1 1 1 2 2 2 3 3 3 4 4 4) + + ; we can use bin for tml-datasets: + +(require '[tablecloth.api :as tc]) +(def ds (tc/dataset {:close (range 15)})) + +(:close ds) + +(bin {:n 5} (:close ds)) + ;; => (0 0 0 1 1 1 2 2 2 3 3 3 4 4 4) + ;; same result. + +(b/bin-full {:n 5} (range 15)) + + ; 5 bins 10-110 + ; 0 10-30 + ; 1 30-50 + ; 2 50-70 + ; 3 70-90 + ; 4 90-110 + +(b/bin-lower-bound {:n-bins 5 :min-x 10 :max-x 110 :range-x 100} 4) + ; 90 +(b/bin-upper-bound {:n-bins 5 :min-x 10 :max-x 110 :range-x 100} 4) + ; 110 +(b/bin-middle {:n-bins 5 :min-x 10 :max-x 110 :range-x 100} 4) + ; 100 + +(def v (range 15)) +(def br (b/bin-full {:step 3.0} v)) + +(b/bin-result br) + +(b/bin-middle br 0) + + + + diff --git a/lib/math/resources/quanta/notebook/math_correlation.clj b/lib/math/resources/quanta/notebook/math_correlation.clj new file mode 100644 index 00000000..c7cc979d --- /dev/null +++ b/lib/math/resources/quanta/notebook/math_correlation.clj @@ -0,0 +1,54 @@ +(ns quanta.notebook.math-correlation + (:require + [tech.v3.datatype.functional :as fun] + [fastmath.stats :as stats] + [ta.math.stats :refer [standardize rand-numbers]])) + +(let [n 100 + xs (repeatedly n #(* 100 (rand))) + ys (map #(+ % (* 200 (rand))) xs)] + [(stats/covariance xs ys) + (stats/correlation xs ys)]) + +(let [n 100 + xs (repeatedly n #(* 100 (rand))) + ys (map #(+ % (* 20 (rand))) xs) + zs (map #(+ % (* 20 (rand))) xs)] + (stats/covariance-matrix [xs ys zs])) + +(let [n 100 + xs (repeatedly n #(* 100 (rand))) + ys (map #(+ % (* 20 (rand))) xs) + zs (map #(+ % (* 20 (rand))) xs)] + (->> [xs ys zs] + (map standardize) + stats/covariance-matrix)) + +(let [n 1000 + xs (repeatedly n #(* 100 (rand))) + ys (map #(+ % (* 20 (rand))) xs) + zs (map #(+ %1 + (- %2) + (* 20 (rand))) + xs + ys)] + (->> [xs ys zs] + (map standardize) + stats/covariance-matrix)) + +(let [n 1000 + xs (-> (rand-numbers n) + (fun/* 100)) + ys (-> xs + (fun/* 20 (rand-numbers n))) + zs (-> xs + (fun/- ys) + (fun/+ (fun/* 20 (rand-numbers n))))] + (->> [xs ys zs] + (map standardize) + stats/covariance-matrix)) + +(fun/quartiles (range 1000)) + +(fun/quartile-1 (range 1000)) + diff --git a/lib/math/resources/quanta/notebook/math_frequencies.clj b/lib/math/resources/quanta/notebook/math_frequencies.clj new file mode 100644 index 00000000..8d4e676e --- /dev/null +++ b/lib/math/resources/quanta/notebook/math_frequencies.clj @@ -0,0 +1,24 @@ +(ns quanta.notebook.math-frequencies + (:require + [com.stuartsierra.frequencies :as freq] + [ta.math.percentile :refer [percentile]])) + +(def example-sequence + (repeatedly 10000 #(rand-int 500))) + +(println (first example-sequence)) + +(frequencies example-sequence) + +(def freq-map (frequencies example-sequence)) + +freq-map + +(freq/stats freq-map) + +(freq/stats freq-map :percentiles [10 20 80 90]) +(freq/stats freq-map :percentiles [80]) + +(percentile 80 example-sequence) + +(percentile 50 example-sequence) diff --git a/lib/quote/deps.edn b/lib/quote/deps.edn index 14771351..eaa2a569 100644 --- a/lib/quote/deps.edn +++ b/lib/quote/deps.edn @@ -1,4 +1,4 @@ -{:paths ["src"] +{:paths ["src" "resources"] :deps {org.clojure/clojure {:mvn/version "1.11.1"} aleph/aleph {:mvn/version "0.7.1"} ; websocket client steam bybit diff --git a/lib/quote/resources/quanta/notebook/quote_feed_fix.clj b/lib/quote/resources/quanta/notebook/quote_feed_fix.clj new file mode 100644 index 00000000..fe52af23 --- /dev/null +++ b/lib/quote/resources/quanta/notebook/quote_feed_fix.clj @@ -0,0 +1,33 @@ +(ns quanta.notebook.quote-feed-fix + (:require + [taoensso.timbre :as timbre :refer [info warn error]] + [manifold.stream :as s] + [ta.quote.fix :refer [create-quotefeed-fix]] + [ta.quote.core :refer [connect disconnect subscribe quote-stream publish!]])) + +;; 1. create quote-feed + +(def feed (create-quotefeed-fix :ctrader-tradeviewmarkets-quote)) +feed +@(:state feed) +(connect feed) +(quote-stream feed) + +;; 2. create consumer , and send a test quote to consumer. + +(defn print-quote [quote] + (info "quote received: " quote)) + +(s/consume print-quote (quote-stream feed)) + +(publish! feed {:asset "QQQ" :price 120.99 :qty 100}) + +;; 3. subscribe to quotes +(subscribe feed "EUR/USD") +(subscribe feed "USD/JPY") +(subscribe feed "USD/SEK") + +;; 4. look to console to see printed messages. + +;; 5. shutdown. +(disconnect feed) diff --git a/lib/quote/resources/quanta/notebook/quote_feed_random.clj b/lib/quote/resources/quanta/notebook/quote_feed_random.clj new file mode 100644 index 00000000..e9953849 --- /dev/null +++ b/lib/quote/resources/quanta/notebook/quote_feed_random.clj @@ -0,0 +1,32 @@ +(ns quanta.notebook.quote-feed-random + (:require + [taoensso.timbre :as timbre :refer [info warn error]] + [manifold.stream :as s] + [ta.quote.random :refer [create-quotefeed-random]] + [ta.quote.core :refer [connect disconnect subscribe quote-stream publish!]])) + +;; 1. create quote-feed + +(def feed (create-quotefeed-random :random)) +feed +@(:state feed) +(connect feed) +(quote-stream feed) + +;; 2. create consumer , and send a test quote to consumer. + +(defn print-quote [quote] + (info "quote received: " quote)) + +(s/consume print-quote (quote-stream feed)) + +(publish! feed {:symbol "QQQ" :price 120.99 :qty 100}) + +;; 3. subscribe to quotes +(subscribe feed "QQQ") +(subscribe feed "MSFT") + +;; 4. look to console to see printed messages. + +;; 5. shutdown. +(disconnect feed) diff --git a/lib/quote/resources/quanta/notebook/quote_manager.clj b/lib/quote/resources/quanta/notebook/quote_manager.clj new file mode 100644 index 00000000..5c106256 --- /dev/null +++ b/lib/quote/resources/quanta/notebook/quote_manager.clj @@ -0,0 +1,45 @@ +(ns quanta.notebook.quote-manager + (:require + [modular.system] + [ta.live.quote-manager :as qm] + [clojure.pprint :refer [print-table]])) + +;; create quote-manager from feeds + +(def feed-fx (modular.system/system :feed-fx)) +(def feed-bybit (modular.system/system :feed-bybit)) +(def feeds {:fx feed-fx :crypto feed-bybit}) +(def q (qm/create-quote-manager feeds)) + +;; use quote-manager from clip +(def q (modular.system/system :quote-manager)) + +;; interact with quote-manager + +(qm/subscribe q {:asset "EUR/USD" :feed :fx}) +(qm/subscribe q {:asset "USD/JPY" :feed :fx}) +(qm/subscribe q {:asset "BTCUSDT" :feed :crypto}) +(qm/subscribe q {:asset "ETHUSDT" :feed :crypto}) + +(qm/quote-snapshot q) +;; => ({:asset "NZD/USD", :price 0.61053, :size 100.0, :feed :fx} +;; {:asset "AUD/USD", :price 0.65303, :size 100.0, :feed :fx} +;; {:asset "USD/CAD", :price 1.355, :size 100.0, :feed :fx} +;; {:asset "EUR/JPY", :price 162.715, :size 100.0, :feed :fx} +;; {:asset "USD/CHF", :price 0.88394, :size 100.0, :feed :fx} +;; {:asset "USD/ZAR", :price 19.08905, :size 100.0, :feed :fx} +;; {:asset "EUR/CHF", :price 0.95793, :size 100.0, :feed :fx} +;; {:asset "GBP/JPY", :price 190.031, :size 100.0, :feed :fx} +;; {:asset "USD/NOK", :price 10.5221, :size 100.0, :feed :fx} +;; {:asset "USD/JPY", :price 150.145, :size 100.0, :feed :fx} +;; {:asset "USD/MXN", :price 17.0115, :size 100.0, :feed :fx} +;; {:asset "USD/SEK", :price 10.3217, :size 100.0, :feed :fx} +;; {:asset "GBP/USD", :price 1.26564, :size 100.0, :feed :fx} +;; {:asset "EUR/USD", :price 1.08372, :size 100.0, :feed :fx} +;; {:asset "BTCUSDT", :price 61976.11, :size 0.001, :feed :bybit} +;; {:asset "ETHUSDT", :price 3418.86, :size 0.05512, :feed :bybit} +;; {:asset "EUR/GBP", :price 0.85629, :size 100.0, :feed :fx}) + +(-> (qm/quote-snapshot q) + print-table) + diff --git a/lib/viz/src/ta/viz/notebook/demo.cljs b/lib/viz/resources/quanta/notebook/viz/demo.cljs similarity index 93% rename from lib/viz/src/ta/viz/notebook/demo.cljs rename to lib/viz/resources/quanta/notebook/viz/demo.cljs index 0025cdf6..b5f48ccd 100644 --- a/lib/viz/src/ta/viz/notebook/demo.cljs +++ b/lib/viz/resources/quanta/notebook/viz/demo.cljs @@ -1,4 +1,4 @@ -(ns ta.viz.notebook.demo +(ns quanta.notebook.viz.demo (:require [ta.viz.renderfn.demo :refer [demo]])) diff --git a/lib/viz/src/ta/viz/notebook/highstock.cljs b/lib/viz/resources/quanta/notebook/viz/highstock.cljs similarity index 97% rename from lib/viz/src/ta/viz/notebook/highstock.cljs rename to lib/viz/resources/quanta/notebook/viz/highstock.cljs index 507fa9bc..f2c26211 100644 --- a/lib/viz/src/ta/viz/notebook/highstock.cljs +++ b/lib/viz/resources/quanta/notebook/viz/highstock.cljs @@ -1,6 +1,6 @@ -(ns ta.viz.notebook.highstock +(ns quanta.notebook.viz.highstock (:require - [ta.viz.renderfn.highstock :refer [highstock]])) + [ta.viz.renderfn.highcharts :refer [highstock]])) (def ohlc-series [[1560864600000,49.01,50.07,48.8,49.61] diff --git a/lib/viz/src/ta/viz/notebook/publish/api.clj b/lib/viz/resources/quanta/notebook/viz/publish/api.clj similarity index 84% rename from lib/viz/src/ta/viz/notebook/publish/api.clj rename to lib/viz/resources/quanta/notebook/viz/publish/api.clj index cf763eb5..42e59131 100644 --- a/lib/viz/src/ta/viz/notebook/publish/api.clj +++ b/lib/viz/resources/quanta/notebook/viz/publish/api.clj @@ -1,4 +1,4 @@ -(ns ta.viz.notebook.publish.api +(ns quanta.notebook.viz.publish.api (:require [ta.viz.publish :as p])) diff --git a/lib/viz/src/ta/viz/notebook/publish/arrow.clj b/lib/viz/resources/quanta/notebook/viz/publish/arrow.clj similarity index 97% rename from lib/viz/src/ta/viz/notebook/publish/arrow.clj rename to lib/viz/resources/quanta/notebook/viz/publish/arrow.clj index 13f17641..7f7b7296 100644 --- a/lib/viz/src/ta/viz/notebook/publish/arrow.clj +++ b/lib/viz/resources/quanta/notebook/viz/publish/arrow.clj @@ -1,4 +1,4 @@ -(ns ta.viz.notebook.publish.arrow +(ns quanta.notebook.viz.publish.arrow (:require [tech.v3.dataset :as dataset] [ta.viz.arrow :as a])) diff --git a/lib/viz/src/ta/viz/notebook/publish/demo.clj b/lib/viz/resources/quanta/notebook/viz/publish/demo.clj similarity index 83% rename from lib/viz/src/ta/viz/notebook/publish/demo.clj rename to lib/viz/resources/quanta/notebook/viz/publish/demo.clj index 99d9c41e..11ae5d18 100644 --- a/lib/viz/src/ta/viz/notebook/publish/demo.clj +++ b/lib/viz/resources/quanta/notebook/viz/publish/demo.clj @@ -1,4 +1,4 @@ -(ns ta.viz.notebook.publish.demo +(ns quanta.notebook.viz.publish.demo (:require [ta.viz.publish :as p])) diff --git a/lib/viz/src/ta/viz/notebook/publish/highstock.clj b/lib/viz/resources/quanta/notebook/viz/publish/highstock.clj similarity index 94% rename from lib/viz/src/ta/viz/notebook/publish/highstock.clj rename to lib/viz/resources/quanta/notebook/viz/publish/highstock.clj index 552da29d..e081e4c0 100644 --- a/lib/viz/src/ta/viz/notebook/publish/highstock.clj +++ b/lib/viz/resources/quanta/notebook/viz/publish/highstock.clj @@ -1,4 +1,4 @@ -(ns ta.viz.notebook.publish.highstock +(ns quanta.notebook.viz.publish.highstock (:require [tick.core :as t] [tablecloth.api :as tc] diff --git a/lib/viz/src/ta/viz/notebook/publish/highstock_raw.clj b/lib/viz/resources/quanta/notebook/viz/publish/highstock_raw.clj similarity index 96% rename from lib/viz/src/ta/viz/notebook/publish/highstock_raw.clj rename to lib/viz/resources/quanta/notebook/viz/publish/highstock_raw.clj index fdb82cc2..e67dede6 100644 --- a/lib/viz/src/ta/viz/notebook/publish/highstock_raw.clj +++ b/lib/viz/resources/quanta/notebook/viz/publish/highstock_raw.clj @@ -1,4 +1,4 @@ -(ns ta.viz.notebook.publish.highstock-raw +(ns quanta.notebook.viz.publish.highstock-raw (:require [ta.viz.publish :as p])) diff --git a/lib/viz/src/ta/viz/notebook/publish/table.clj b/lib/viz/resources/quanta/notebook/viz/publish/table.clj similarity index 94% rename from lib/viz/src/ta/viz/notebook/publish/table.clj rename to lib/viz/resources/quanta/notebook/viz/publish/table.clj index 9e3a30cc..7e5d6263 100644 --- a/lib/viz/src/ta/viz/notebook/publish/table.clj +++ b/lib/viz/resources/quanta/notebook/viz/publish/table.clj @@ -1,4 +1,4 @@ -(ns ta.viz.notebook.publish.table +(ns quanta.notebook.viz.publish.table (:require [tablecloth.api :as tc] [ta.viz.publish :as p])) diff --git a/lib/viz/src/ta/viz/notebook/publish/vega.clj b/lib/viz/resources/quanta/notebook/viz/publish/vega.clj similarity index 95% rename from lib/viz/src/ta/viz/notebook/publish/vega.clj rename to lib/viz/resources/quanta/notebook/viz/publish/vega.clj index 4c503ce3..dacc8698 100644 --- a/lib/viz/src/ta/viz/notebook/publish/vega.clj +++ b/lib/viz/resources/quanta/notebook/viz/publish/vega.clj @@ -1,4 +1,4 @@ -(ns ta.viz.notebook.publish.vega +(ns quanta.notebook.viz.publish.vega (:require [ta.viz.publish :as p])) diff --git a/lib/viz/src/ta/viz/notebook/render.cljs b/lib/viz/resources/quanta/notebook/viz/render.cljs similarity index 95% rename from lib/viz/src/ta/viz/notebook/render.cljs rename to lib/viz/resources/quanta/notebook/viz/render.cljs index bd79759f..13b0bd00 100644 --- a/lib/viz/src/ta/viz/notebook/render.cljs +++ b/lib/viz/resources/quanta/notebook/viz/render.cljs @@ -1,4 +1,4 @@ -(ns ta.viz.notebook.render +(ns quanta.notebook.viz.render (:require [ta.viz.renderfn :refer [render]])) diff --git a/lib/viz/src/ta/viz/notebook/rtable.cljs b/lib/viz/resources/quanta/notebook/viz/rtable.cljs similarity index 94% rename from lib/viz/src/ta/viz/notebook/rtable.cljs rename to lib/viz/resources/quanta/notebook/viz/rtable.cljs index 3690c0d9..cbeede65 100644 --- a/lib/viz/src/ta/viz/notebook/rtable.cljs +++ b/lib/viz/resources/quanta/notebook/viz/rtable.cljs @@ -1,4 +1,4 @@ -(ns ta.viz.notebook.rtable +(ns quanta.notebook.viz.rtable (:require [ta.viz.renderfn.rtable :refer [rtable]])) diff --git a/lib/viz/src/ta/viz/notebook/scratchpad.clj b/lib/viz/resources/quanta/notebook/viz/scratchpad.clj similarity index 97% rename from lib/viz/src/ta/viz/notebook/scratchpad.clj rename to lib/viz/resources/quanta/notebook/viz/scratchpad.clj index 22e97504..6a9c4481 100644 --- a/lib/viz/src/ta/viz/notebook/scratchpad.clj +++ b/lib/viz/resources/quanta/notebook/viz/scratchpad.clj @@ -1,4 +1,4 @@ -(ns ta.viz.notebook.scratchpad) +(ns quanta.notebook.viz.scratchpad) ;; open webbrowser on port 8080, then go to devtools->scratchpad ;; evaling one of the forms below will show the visualization diff --git a/lib/viz/src/ta/viz/notebook/vega.cljs b/lib/viz/resources/quanta/notebook/viz/vega.cljs similarity index 96% rename from lib/viz/src/ta/viz/notebook/vega.cljs rename to lib/viz/resources/quanta/notebook/viz/vega.cljs index b0197425..162136c0 100644 --- a/lib/viz/src/ta/viz/notebook/vega.cljs +++ b/lib/viz/resources/quanta/notebook/viz/vega.cljs @@ -1,4 +1,4 @@ -(ns ta.viz.notebook.vega +(ns quanta.notebook.viz.vega (:require [ta.viz.renderfn.vega :refer [vegalite]]))