diff --git a/app/demo/src/demo/goldly/page/tvalgo.cljs b/app/demo/src/demo/goldly/page/tvalgo.cljs index 2f2f0a03..80819a66 100644 --- a/app/demo/src/demo/goldly/page/tvalgo.cljs +++ b/app/demo/src/demo/goldly/page/tvalgo.cljs @@ -5,12 +5,12 @@ [goldly.service.core :refer [run-a]] [goldly.page :as page] [input] - [ta.tradingview.goldly.tradingview :as tv :refer [tradingview-chart]] [ta.tradingview.goldly.algo.context :as c] - [ta.tradingview.goldly.feed.algo2 :refer [get-tradingview-options-algo-feed]] ;[ta.tradingview.goldly.interact :refer [set-symbol state track-range reset-data]] [demo.goldly.lib.ui :refer [link-href]] - [demo.goldly.algo.dialog :refer [show-algo-dialog show-table-dialog]])) + [demo.goldly.algo.dialog :refer [show-algo-dialog show-table-dialog]] + [ta.tradingview.goldly.algo.tradingview :refer [tradingview-algo]] + )) (defonce algo-ctx (c/create-algo-context "moon" {:symbol "QQQ" :frequency "D"})) @@ -65,29 +65,25 @@ [:span (pr-str @state)])) (defn algo-menu [] + (let [algo-input (c/get-algo-input-atom algo-ctx)] + (fn [] [:div.flex.flex-row.bg-blue-500 [link-href "/" "main"] [input/select {:nav? false :items (or (:algos @algo-state) [])} - algo-state [:algo]] + algo-input [:algo]] [input/select {:nav? false :items (:symbols @algo-state)} - algo-state [:symbol]] + algo-input [:opts :symbol]] [input/button {:on-click #(show-algo-dialog algo-ctx)} "options"] ;[input/button {:on-click #(reset-data)} "R!"] [input/button {:on-click #(show-table-dialog algo-ctx)} "table"] ;[input/button {:on-click get-window-demo} "get window"] ;[tv-status] - ]) + ]))) + -(defn tradingview-algo [algo-ctx] - (let [{:keys [algo opts]} (c/get-algo-input algo-ctx) - symbol (:symbol opts)] - (println "showing tradingview-widget algo-mode algo: " algo " symbol: " symbol) - [tradingview-chart {:feed (get-tradingview-options-algo-feed algo-ctx) - :options {:autosize true - :symbol symbol}}])) (defn algo-ui [] (fn [] diff --git a/lib/tradingview/src/ta/tradingview/goldly/algo/context.cljs b/lib/tradingview/src/ta/tradingview/goldly/algo/context.cljs index e4baff68..10a0d7be 100644 --- a/lib/tradingview/src/ta/tradingview/goldly/algo/context.cljs +++ b/lib/tradingview/src/ta/tradingview/goldly/algo/context.cljs @@ -1,9 +1,11 @@ -(ns ta.tradingview.goldly.algo.context) +(ns ta.tradingview.goldly.algo.context + (:require + [reagent.core :as r])) (defn create-algo-context [algo opts] - (let [data (atom nil) - input (atom {:algo algo - :opts opts}) + (let [data (r/atom nil) + input (r/atom {:algo algo + :opts opts}) context {:input input :data data}] context)) @@ -14,6 +16,9 @@ (defn get-algo-name [algo-ctx] (-> algo-ctx :input deref :algo)) +(defn get-algo-input-atom [algo-ctx] + (-> algo-ctx :input)) + (defn get-data [algo-ctx] (-> algo-ctx :data deref)) diff --git a/lib/tradingview/src/ta/tradingview/goldly/algo/interaction.cljs b/lib/tradingview/src/ta/tradingview/goldly/algo/interaction.cljs new file mode 100644 index 00000000..8a6aff5a --- /dev/null +++ b/lib/tradingview/src/ta/tradingview/goldly/algo/interaction.cljs @@ -0,0 +1,36 @@ +(ns ta.tradingview.goldly.algo.interaction + (:require + [ta.tradingview.goldly.algo.context :as c] + [ta.tradingview.goldly.interact2 :as i] + )) + +(defn symbol-changed? [old-value new-value] + (let [old (get-in old-value [:opts :symbol]) + new (get-in new-value [:opts :symbol])] + (println "symbol old: " old " new: " new) + (if (= old new) + false + true))) + +(defn on-load-finished [& args] + (println "on-load-finished: " args) + ) + +(defn on-symbol-change [algo-ctx tv s] + (println "symbol changed to: " s) + (let [{:keys [algo opts]} (c/get-algo-input algo-ctx) + {:keys [symbol frequency]} opts] + (c/set-algo-data algo-ctx nil) + (i/set-symbol tv s frequency on-load-finished) + nil)) + +(defn track-interactions [algo-ctx tv] + (let [input (c/get-algo-input-atom algo-ctx)] + (println "add-watch to algo-ctx input ..") + (add-watch input :algo-input + (fn [key state old-value new-value] + (println "algo-ctx input changed to:" new-value) + (when (symbol-changed? old-value new-value) + (on-symbol-change algo-ctx tv (get-in new-value [:opts :symbol]))) + + )))) \ No newline at end of file diff --git a/lib/tradingview/src/ta/tradingview/goldly/algo/tradingview.cljs b/lib/tradingview/src/ta/tradingview/goldly/algo/tradingview.cljs new file mode 100644 index 00000000..3fc06f6f --- /dev/null +++ b/lib/tradingview/src/ta/tradingview/goldly/algo/tradingview.cljs @@ -0,0 +1,69 @@ +(ns ta.tradingview.goldly.algo.tradingview + (:require + [reagent.core :as r] + [js-loader :refer [with-js browser-defined?]] + [ta.tradingview.goldly.tradingview :as tv :refer [tradingview-chart show-tradingview-widget shutdown-tradingview!]] + [ta.tradingview.goldly.feed.algo2 :refer [get-tradingview-options-algo-feed]] + [ta.tradingview.goldly.algo.context :as c] + [ta.tradingview.goldly.algo.interaction :as i] + )) + + +#_(defn tradingview-algo-widget [algo-ctx] + (let [{:keys [algo opts]} (c/get-algo-input algo-ctx) + symbol (:symbol opts)] + (println "showing tradingview-widget algo-mode algo: " algo " symbol: " symbol) + [tradingview-chart {:feed (get-tradingview-options-algo-feed algo-ctx) + :options {:autosize true + :symbol symbol}}] + )) + + +#_(defn tradingview-algo [algo-ctx] + ;(i/track-interactions algo-ctx) ; interactions tracking does not work. + (tradingview-algo-widget algo-ctx) + ) + + +(defn tradingview-widget-algo [algo-ctx] + (let [id "tv-widget-1" ;(uuid/uuid-string (uuid/make-random-uuid)) + tv (r/atom nil)] + (r/create-class + {:display-name "tradingview" + :reagent-render (fn [_] + [:div {:id id :style {:width "100%" :height "100%"}}]) + :component-did-mount (fn [_] + (println "TradingViewChart.ComponentDidMount") + (let [{:keys [algo opts]} (c/get-algo-input algo-ctx) + symbol (:symbol opts) + widget (show-tradingview-widget + id + {:feed (get-tradingview-options-algo-feed algo-ctx) + :options {:autosize true + :symbol symbol}})] + (reset! tv widget) + (i/track-interactions algo-ctx @tv) + (.onChartReady @tv #(println "TradingView ChartWidget has loaded!")))) + :component-will-unmount (fn [this] + (println "TradingViewChart.ComponentDid-UN-Mount") + (shutdown-tradingview! @tv)) + ;:component-will-receive-props (fn [this new-argv] + ; (println "receive props: " new-argv)) + :component-did-update (fn [this [_ prev-props prev-more]] + (println "tradingview-algo-widget did update.") + ;(let [[_ new-config] (r/argv this)] + ; (println "TradingViewChart.ComponentDidUpdate " new-config) + ;(if (not (= + ;(reset! tv (change-feed-config id new-config @tv)) + ; ) + )}))) + + +(defn tradingview-algo [algo-ctx] + [with-js + {(browser-defined? "TradingView") "/r/tradingview/charting_library_21/charting_library.js" ; "/r/tradingview/charting_library.min.js" ; js/TradingView + (browser-defined? "Datafeeds") "/r/tradingview/UDF_21/bundle.js" ; "/r/tradingview/UDF/bundle.js" + (browser-defined? "MyStudy") "/r/tradingview/study.js"} ; js/Datafeeds + ;[:h1 "tv loaded!"] + [tradingview-widget-algo algo-ctx]]) + diff --git a/lib/tradingview/src/ta/tradingview/goldly/feed/algo2.cljs b/lib/tradingview/src/ta/tradingview/goldly/feed/algo2.cljs index dcf0e1b1..894cdb1a 100644 --- a/lib/tradingview/src/ta/tradingview/goldly/feed/algo2.cljs +++ b/lib/tradingview/src/ta/tradingview/goldly/feed/algo2.cljs @@ -151,20 +151,19 @@ (get-bars algo-ctx period-clj onHistoryCallback onErrorCallback) nil)) :subscribeBars (fn [symbolInfo resolution _onRealtimeCallback subscribeUID _onResetCacheNeededCallback] - ;(println "subscribe: " symbolInfo resolution subscribeUID) + (println "subscribe-bars: " symbolInfo resolution subscribeUID) ) :unsubscribeBars (fn [subscriberUID] - ;(println "unsubscribe: " subscriberUID) + (println "unsubscribe-bars: " subscriberUID) ) :getServerTime (fn [onTimeCallback] - (let [cb (fn [[_ data]] ; _ = event-type - (let [{:keys [result _error]} data - result-js (clj->js result)] - ;(println "TV TIME: " result) - (onTimeCallback result-js)))] - (run-cb {:fun 'ta.tradingview.handler-datasource/time-handler - :args [] - :cb cb}))) + (let [rp (clj 'ta.tradingview.handler-datasource/server-time)] + (p/then rp (fn [time] + (println "TV TIME: " time) + (onTimeCallback (clj->js time)))) + (p/catch rp (fn [err] + (println "ERROR GETTING SERVER TIME: " err))))) + :calculateHistoryDepth (fn [resolution resolutionBack intervalBack] (println "calculate history depth:" resolution resolutionBack intervalBack)) @@ -187,6 +186,7 @@ #_(run-cb {:fun 'ta.algo.manager/algo-marks :args [algo symbol frequency options epoch-start epoch-end] :cb cb}) + (onDataCallback (clj->js [])) )) :getTimeScaleMarks (fn [symbolInfo startDate endDate _onDataCallback resolution] ;(println "get-timescale-marks" symbolInfo startDate endDate resolution) diff --git a/lib/tradingview/src/ta/tradingview/goldly/interact.cljs b/lib/tradingview/src/ta/tradingview/goldly/interact.cljs index eb5c8583..8758a5d7 100644 --- a/lib/tradingview/src/ta/tradingview/goldly/interact.cljs +++ b/lib/tradingview/src/ta/tradingview/goldly/interact.cljs @@ -17,13 +17,17 @@ (.activeChart @tv-widget-atom)) (defn on-data-loaded [& _args] - ;(println "tv data has been loaded (called after set-symbol)") + (println "tv data has been loaded (called after set-symbol)") ) -(defn set-symbol [symbol interval] - ;(println "tv set symbol:" symbol "interval: " interval) - (.setSymbol @tv-widget-atom symbol interval on-data-loaded) - nil) +(defn set-symbol + ([symbol interval] + ;(println "tv set symbol:" symbol "interval: " interval) + (set-symbol symbol interval on-data-loaded)) + ([symbol interval on-load-finished] + ;(println "tv set symbol:" symbol "interval: " interval) + (.setSymbol @tv-widget-atom symbol interval on-load-finished) + nil)) (defn study-list [] (-> (.getStudiesList @tv-widget-atom) diff --git a/lib/tradingview/src/ta/tradingview/goldly/interact2.cljs b/lib/tradingview/src/ta/tradingview/goldly/interact2.cljs new file mode 100644 index 00000000..211782b1 --- /dev/null +++ b/lib/tradingview/src/ta/tradingview/goldly/interact2.cljs @@ -0,0 +1,17 @@ +(ns ta.tradingview.goldly.interact2 + (:require + [reagent.core :as r])) + + + +(defn on-data-loaded [& _args] + (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)) \ No newline at end of file diff --git a/lib/tradingview/src/ta/tradingview/goldly/tradingview.cljs b/lib/tradingview/src/ta/tradingview/goldly/tradingview.cljs index e6043abd..41e2b10b 100644 --- a/lib/tradingview/src/ta/tradingview/goldly/tradingview.cljs +++ b/lib/tradingview/src/ta/tradingview/goldly/tradingview.cljs @@ -119,6 +119,12 @@ (set! (.-widget js/window) tv-widget) tv-widget)) +(defn shutdown-tradingview! [tv] + (println "shutting down tradingview ..") + (if (nil? tv) + (println "tv is nil. Not calling shutdown.") + (.remove tv))) + (defn tradingview-chart [options] [with-js {(browser-defined? "TradingView") "/r/tradingview/charting_library_21/charting_library.js" ; "/r/tradingview/charting_library.min.js" ; js/TradingView diff --git a/lib/tradingview/src/ta/tradingview/handler_datasource.clj b/lib/tradingview/src/ta/tradingview/handler_datasource.clj index 425e77cc..fb891dee 100644 --- a/lib/tradingview/src/ta/tradingview/handler_datasource.clj +++ b/lib/tradingview/src/ta/tradingview/handler_datasource.clj @@ -21,7 +21,7 @@ (defn server-time [] (-> (now-datetime) datetime->epoch-second)) -(defn time-handler [_] +(defn time-handler [] (info "tv/time") (let [now-epoch (server-time)] (res/response (str now-epoch)))) @@ -84,7 +84,7 @@ :volume_precision 0 ;Integer showing typical volume value decimal places for a particular symbol. 0 means volume is always an integer. 1 means that there might be 1 numeric character after the comma. :pointvalue 1 ; session - :data_status "streaming" ; + :data_status "endofday" ; streaming endofday pulsed delayed_streaming delayed delayed_streaming :has_intraday true :timezone "Etc/UTC" ; "America/New_York" :session "0900-1600" ;"0900-1630|0900-1400:2", @@ -93,6 +93,8 @@ ; :expired true ; whether this symbol is an expired futures contract or not. ; :expiration_date (to-epoch-no-ms- (-> 1 t/hours t/ago)) })) + + (comment ; stocks should have :exchange SG :type Stocks ; crypto should have :exchange BB :type Crypto