diff --git a/app/demo/deps.edn b/app/demo/deps.edn index e1978b61..c81acae8 100644 --- a/app/demo/deps.edn +++ b/app/demo/deps.edn @@ -1,5 +1,5 @@ {:paths ["src" - "classes" + ;"classes" ] :deps {org.clojure/clojure {:mvn/version "1.11.1"} aysylu/loom {:mvn/version "1.0.2"} diff --git a/app/demo/src/demo/algo/astro.clj b/app/demo/src/demo/algo/astro.clj index 105e22c9..f13bd25c 100644 --- a/app/demo/src/demo/algo/astro.clj +++ b/app/demo/src/demo/algo/astro.clj @@ -11,3 +11,6 @@ {:volume "column"}] :options {:show-moon false} :marks astro-marks}) + + + diff --git a/app/demo/src/demo/goldly/repl/tradingview/admin.clj b/app/demo/src/demo/goldly/repl/tradingview/admin.clj index 2d46ff5d..857c7636 100644 --- a/app/demo/src/demo/goldly/repl/tradingview/admin.clj +++ b/app/demo/src/demo/goldly/repl/tradingview/admin.clj @@ -24,42 +24,6 @@ ;(set! (.-bongo js/globalThis) i-clj) -(eval-code! - (add-header-button - "re-gann" "my tooltip" - (fn [] - (println "button clicked ")))) - -(eval-code! - (ta.tradingview.goldly.interact/add-context-menu - [{"position" "top" - "text" (str "First top menu item"); , time: " unixtime ", price: " price) - "click" (fn [] (js/alert "First clicked."))} - {:text "-" - :position "top"} - {:text "-Objects Tree..."} - {:position "top" - :text "Second top menu item 2" - :click (fn [] (js/alert "second clicked."))} - {:position "bottom" - :text "Bottom menu item" - :click (fn [] (js/alert "third clicked."))}])) - -(eval-code! - (deref tvalgo/algo-state)) - -(eval-code! - (deref tvalgo/window-state)) - -(eval-code! - (do (ta.tradingview.goldly.interact/demo-crosshair) - (ta.tradingview.goldly.interact/demo-range))) - -(eval-code! - (ta.tradingview.goldly.interact/get-range)) - -(eval-code! - (ta.tradingview.goldly.interact/track-range)) (eval-code! (deref tv/state)) @@ -111,8 +75,6 @@ ;(set! (.-foo js/globalThis) foo) (js/eval "new foo().a"))) -(eval-code! - (tv/add-demo-menu)) (eval-code! (set-symbol "TLT" "1D")) @@ -122,13 +84,7 @@ ;"BB:BTCUSD" -(eval-code! - (let [p (tv/set-range - {:from 1420156800 :to 1451433600} - {:percentRightMargin 30})] - (.then p (fn [] (println "new visible range applied!") - ;widget.activeChart () .refreshMarks (); - )))) + ;widget.selectedLineTool () ; returns "cursor" ;widget.activeChart () .getAllShapes () .forEach (({name}) => console.log (name)); ;widget.activeChart().setPriceToBarRatio(0.7567, { disableUndo: true }); @@ -136,5 +92,6 @@ ;widget.activeChart () .getTimeScaleLogicalRange () +; not working - tradingview widget does not have layout features (eval-code! - (ta.tradingview.goldly.interact2/set-layout "2h")) \ No newline at end of file + (ta.tradingview.goldly.interact2/set-layout "2h")) diff --git a/app/demo/src/demo/goldly/repl/tradingview/algo.clj b/app/demo/src/demo/goldly/repl/tradingview/algo.clj index d8c4df87..8328965a 100644 --- a/app/demo/src/demo/goldly/repl/tradingview/algo.clj +++ b/app/demo/src/demo/goldly/repl/tradingview/algo.clj @@ -1,6 +1,6 @@ (ns demo.goldly.repl.tradingview.algo (:require - [eval.cljs-eval :refer [eval-code!]])) + [reval.cljs-eval :refer [eval-code!]])) (eval-code! (+ 5 5)) diff --git a/app/demo/src/demo/goldly/repl/tradingview/execution.clj b/app/demo/src/demo/goldly/repl/tradingview/execution.clj index 123e912b..8d16a12d 100644 --- a/app/demo/src/demo/goldly/repl/tradingview/execution.clj +++ b/app/demo/src/demo/goldly/repl/tradingview/execution.clj @@ -1,6 +1,7 @@ (ns demo.goldly.repl.tradingview.execution (:require - [eval.cljs-eval :refer [eval-code!]])) + [reval.cljs-eval :refer [eval-code!]])) + (eval-code! (-> (tv/chart-active) diff --git a/app/demo/src/demo/goldly/repl/tradingview/menu.clj b/app/demo/src/demo/goldly/repl/tradingview/menu.clj new file mode 100644 index 00000000..c88c1221 --- /dev/null +++ b/app/demo/src/demo/goldly/repl/tradingview/menu.clj @@ -0,0 +1,32 @@ +(ns demo.goldly.repl.tradingview.menu + (:require + [reval.cljs-eval :refer [eval-code!]])) + + + + +(eval-code! + (ta.tradingview.goldly.interact2/add-header-button + @ta.tradingview.goldly.interact/tv-widget-atom + "re-gann" "my tooltip" + (fn [] + (js/alert "re-gann button clicked ")))) + + +(eval-code! + (ta.tradingview.goldly.interact2/add-context-menu + @ta.tradingview.goldly.interact/tv-widget-atom + [{"position" "top" + "text" (str "First top menu item"); , time: " unixtime ", price: " price) + "click" (fn [] (js/alert "First clicked."))} + {:text "-" + :position "top"} + {:text "-Paste"} ; Removes the existing item from the menu + {:text "-" ; Adds a separator between buttons + :position "top"} + {:position "top" + :text "Second top menu item 2" + :click (fn [] (js/alert "second clicked."))} + {:position "bottom" + :text "Bottom menu item" + :click (fn [] (js/alert "third clicked."))}])) \ No newline at end of file diff --git a/app/demo/src/demo/goldly/repl/tradingview/move.clj b/app/demo/src/demo/goldly/repl/tradingview/move.clj new file mode 100644 index 00000000..40adca92 --- /dev/null +++ b/app/demo/src/demo/goldly/repl/tradingview/move.clj @@ -0,0 +1,79 @@ +(ns demo.goldly.repl.tradingview.move + (:require + [ta.helper.date :as dt :refer [parse-date ->epoch-second epoch-second->datetime]] + [reval.cljs-eval :refer [eval-code!]])) + +(eval-code! + (ta.tradingview.goldly.interact2/get-range + @ta.tradingview.goldly.interact/tv-widget-atom + )) +;; {:from 1644796800, :to 1697155200} + +(eval-code! + (ta.tradingview.goldly.interact/track-range)) + + + +(defn epoch [yyyy-mm-dd] + (-> yyyy-mm-dd parse-date ->epoch-second)) + +(epoch "2023-01-01") +;; => 1672531200 + +(epoch "2023-12-31") +;; => 1703980800 + +(epoch "2022-01-01") +;; => 1640995200 + +(epoch "2022-12-31") +;; => 1672444800 + +(epoch "2019-04-01") +;; => 1554076800 + +;; => Syntax error compiling at (src/demo/goldly/repl/tradingview/move.clj:32:1). +;; Unable to resolve symbol: epoch in this context + +;; => 1672444800 +(eval-code! ; year 2023 + (let [p (ta.tradingview.goldly.interact2/set-range + @ta.tradingview.goldly.interact/tv-widget-atom + {:from 1672531200 + :to 1703980800 } + ;{:percentRightMargin 5} + {} + )] + (.then p (fn [] + (println "new visible range applied!") + ;widget.activeChart () .refreshMarks (); + )))) + +(eval-code! ; year 2022 + (let [p (ta.tradingview.goldly.interact2/set-range + @ta.tradingview.goldly.interact/tv-widget-atom + {:from 1640995200 + :to 1672444800} + {} + ;{:percentRightMargin 5} + )] + (.then p (fn [] + (println "new visible range applied!") + ;widget.activeChart () .refreshMarks (); + )))) + + +(eval-code! ; 2019-04-01 (as midpoint in the chart) + (ta.tradingview.goldly.interact2/goto-date! + @ta.tradingview.goldly.interact/tv-widget-atom + 1554076800)) +;set-visible-range {:from 1545868800, :to 1562284800} {:percentRightMargin 5} + +(epoch-second->datetime 1554076800) +(epoch-second->datetime 1545868800) +(epoch-second->datetime 1562284800) + +; widget.onChartReady(() => { +; const chart = widget.chart(); +; chart.setTimeFrame({val: {type: 'period-back', value: '12M'}, res: '1W'}); +; }); \ No newline at end of file diff --git a/app/demo/src/demo/goldly/repl/tradingview/shape.clj b/app/demo/src/demo/goldly/repl/tradingview/shape.clj index e15f1485..f38b5b91 100644 --- a/app/demo/src/demo/goldly/repl/tradingview/shape.clj +++ b/app/demo/src/demo/goldly/repl/tradingview/shape.clj @@ -1,6 +1,6 @@ (ns demo.goldly.repl.tradingview.shape (:require - [eval.cljs-eval :refer [eval-code!]])) + [reval.cljs-eval :refer [eval-code!]])) (eval-code! (+ 5 5)) diff --git a/app/demo/src/demo/goldly/repl/tradingview/study.clj b/app/demo/src/demo/goldly/repl/tradingview/study.clj index 08df6be1..511e74d8 100644 --- a/app/demo/src/demo/goldly/repl/tradingview/study.clj +++ b/app/demo/src/demo/goldly/repl/tradingview/study.clj @@ -5,7 +5,6 @@ (eval-code! (+ 5 5)) - (eval-code! (ta.tradingview.goldly.interact/add-study "Moving Average" [30 "close"])) diff --git a/lib/tradingview/src/ta/tradingview/goldly/algo/tradingview.cljs b/lib/tradingview/src/ta/tradingview/goldly/algo/tradingview.cljs index 185983b2..6c0993a8 100644 --- a/lib/tradingview/src/ta/tradingview/goldly/algo/tradingview.cljs +++ b/lib/tradingview/src/ta/tradingview/goldly/algo/tradingview.cljs @@ -45,6 +45,7 @@ :custom_indicators_getter (config/algo-all-custom-indicator-promise algo-ctx) }})] (reset! tv widget) + (set! (-> js/window .-tvwidget) widget) (i/track-interactions algo-ctx widget) (.onChartReady @tv #(println "TradingView ChartWidget has loaded!")))) :component-will-unmount (fn [this] diff --git a/lib/tradingview/src/ta/tradingview/goldly/interact2.cljs b/lib/tradingview/src/ta/tradingview/goldly/interact2.cljs index 59137953..07f2a746 100644 --- a/lib/tradingview/src/ta/tradingview/goldly/interact2.cljs +++ b/lib/tradingview/src/ta/tradingview/goldly/interact2.cljs @@ -2,33 +2,55 @@ (:require [reagent.core :as r])) +; to get all functions that the widget supports +;TradingView.widget.prototype -; same as interact namespace, but requires tv (tradingview-widget) parameter +;; EVENTS -(defn on-data-loaded [& _args] - (println "tv data has been loaded (called after set-symbol)")) +; window.tvWidget.activeChart().dataReady(() => { -(defn set-symbol - ([tv symbol interval] - ;(println "tv set symbol:" symbol "interval: " interval) - (set-symbol tv symbol interval on-data-loaded)) - ([tv symbol interval on-load-finished] - (println "tv set symbol:" symbol "interval: " interval) - (.setSymbol tv symbol interval on-load-finished) - nil)) +(defn wrap-chart-ready [tv f] + ; It's now safe to call any other methods of the widget + (.onChartReady tv f)) + +; (wrap-chart-ready (fn [] (println "chart ready!"))) +(defn wrap-header-ready [tv f] + ; A promise that resolves if and when the header is ready to be used. + ; headerReady() => Promise + (.headerReady tv f)) + +;; DEBUG + +(defn set-debug-mode [tv enabled?] + (println "set-debug-mode: " enabled?) + (.setDebugMode tv enabled?)) + +;; HELPER FNS (defn chart-active [tv] (.activeChart tv)) - (defn reset-data [tv] (let [chart (chart-active tv)] - (println "reset-data! (of active chart)") + (println "reset-data! (of active chart)") (.resetData chart) nil)) +;; SYMBOL + +(defn- on-data-loaded [& _args] + ; used by set-symbol + (println "tv data has been loaded (called after set-symbol)")) +(defn set-symbol + ([tv symbol interval] + ;(println "tv set symbol:" symbol "interval: " interval) + (set-symbol tv symbol interval on-data-loaded)) + ([tv symbol interval on-load-finished] + (println "tv set symbol:" symbol "interval: " interval) + (.setSymbol tv symbol interval on-load-finished) + nil)) ;; STUDY / INDICAOR @@ -37,9 +59,8 @@ (.log js/console) (js->clj studies-js))) -; JSServer.studyLibrary.push.apply(JSServer.studyLibrary,e) - (defn add-study [tv study-name study-args] + ; JSServer.studyLibrary.push.apply(JSServer.studyLibrary,e) (let [chart (chart-active tv) study-args-js (-> study-args vec clj->js)] (println "add study: " study-name " args:" study-args) @@ -64,7 +85,6 @@ time (.-time r)] {:price price :time time})) - (defn on-crosshair-moved [tv f] (let [chart (chart-active tv) cross-hair (.crossHairMoved chart) @@ -93,15 +113,14 @@ ; Returns the object {from, to} . from and to are boundaries of the price scale visible range in main series area. ; Date.UTC (2018, 0, 1) / 1000 -(defn set-range [tv {:keys [_from _to] :as range} opts] ; Date.UTC (2012, 2, 3) / 1000, +(defn set-range [tv range opts] ; Date.UTC (2012, 2, 3) / 1000, + (println "set-visible-range " range opts) (let [chart (chart-active tv) range-js (clj->js range) opts (or opts {}) opts-js (clj->js opts)] (-> (.setVisibleRange chart range-js opts-js)))) - - (defn on-range-change [tv f] (let [chart (chart-active tv) visible-range (.onVisibleRangeChanged chart) @@ -109,28 +128,23 @@ (f (extract-range r)))] (.subscribe visible-range nil wrapped-f))) +(defn goto-date! [tv epoch] + (let [{:keys [from to]} (get-range tv) + diff (- to from) + half (.round js/Math (/ diff 2)) + from (- epoch half) + to (+ epoch half)] + (println "goto-date! date: " epoch " from: " from " to: " to) + (set-range tv + {:from from :to to} + {}))) + ;; features (defn show-features [tv] (let [features (.getAllFeatures tv)] (.keys js/Object features))) -;; EVENTS - -; window.tvWidget.activeChart().dataReady(() => { - -(defn wrap-chart-ready [tv f] - ; It's now safe to call any other methods of the widget - (.onChartReady tv f)) - -; (wrap-chart-ready (fn [] (println "chart ready!"))) - -(defn wrap-header-ready [tv f] - ; A promise that resolves if and when the header is ready to be used. - ; headerReady() => Promise - (.headerReady tv f)) - - ;; SHAPE (defn add-shape [tv points shape] @@ -206,11 +220,7 @@ ;(println "menu-js: " menu-js) (.onContextMenu tv add-context-menu))) -;; DEBUG -(defn set-debug-mode [tv enabled?] - (println "set-debug-mode: " enabled?) - (.setDebugMode tv enabled?)) ;; LAYOUT