From 9a0b4487b387af08015d8d92bc4c31ecadb32ee0 Mon Sep 17 00:00:00 2001 From: awb99 Date: Mon, 4 Sep 2023 15:46:22 -0500 Subject: [PATCH] algo-charts symbol switching working --- app/demo/src/demo/algo/moon.clj | 91 ++++++++++++---- app/demo/src/demo/goldly/page/tvalgo.cljs | 57 ++-------- app/resources/symbollist/equity-style.edn | 2 +- app/resources/symbollist/test.edn | 4 +- lib/astro/src/astro/marks.clj | 5 +- lib/helper/src/ta/helper/ago.clj | 8 +- .../tradingview/goldly/algo/interaction.cljs | 13 ++- .../src/ta/tradingview/goldly/feed/algo2.cljs | 103 +++++++++--------- .../ta/tradingview/goldly/tradingview.cljs | 4 +- .../src/ta/tradingview/handler_datasource.clj | 4 +- lib/trateg/deps.edn | 1 + lib/trateg/src/ta/algo/manager.clj | 50 ++++++--- .../src/ta/backtest/roundtrip_backtest.clj | 63 +++++++++-- 13 files changed, 243 insertions(+), 162 deletions(-) diff --git a/app/demo/src/demo/algo/moon.clj b/app/demo/src/demo/algo/moon.clj index 0c33da6a..991a4b19 100644 --- a/app/demo/src/demo/algo/moon.clj +++ b/app/demo/src/demo/algo/moon.clj @@ -2,20 +2,17 @@ (:require [tablecloth.api :as tc] [tech.v3.datatype :as dtype] - [ta.algo.manager :refer [add-algo]] + [ta.algo.manager :refer [add-algo] :as am] [astro.moon :refer [inst->moon-phase-kw phase->text]] [ta.tradingview.chart.shape :as shapes] [ta.tradingview.chart.plot :refer [plot-type]] [ta.tradingview.chart.color :refer [color]] - )) + )) -(defn add-moon-indicator [ds-bars _] - (tc/add-column - ds-bars - :phase - (dtype/emap inst->moon-phase-kw :object (:date ds-bars)))) +(defn moon-phase [col-date] + (dtype/emap inst->moon-phase-kw :object col-date)) -(defn calc-moon-signal [phase] +(defn moon-phase->signal [phase] (if phase (case phase :i1 :flat @@ -23,23 +20,28 @@ :hold) :hold)) +(defn moon-signal [moon-phase] + (dtype/emap moon-phase->signal :object moon-phase)) + (defn buy-signal->text [signal] (if (= signal :buy) 1.0 nil)) -(defn add-buy-signal-bool [ds-bars] - (tc/add-column - ds-bars - :signal-text - (dtype/emap buy-signal->text :bool (:signal ds-bars)))) +(defn signal-text [signal] + (dtype/emap buy-signal->text :object signal)) -(defn moon-signal [ds-bars options] - (let [ds-study (add-moon-indicator ds-bars options) - signal (into [] (map calc-moon-signal (:phase ds-study)))] - (-> ds-study - (tc/add-columns {:signal signal}) - (add-buy-signal-bool)))) +(defn moon-study [ds-bars options] + (let [col-date (:date ds-bars) + col-moon-phase (moon-phase col-date) + col-moon-signal (moon-signal col-moon-phase) + col-signal-text (signal-text col-moon-signal)] + (-> ds-bars + (tc/add-columns {:moon-phase col-moon-phase + :signal col-moon-signal + :signal-text col-signal-text + }) + ))) ;; SHAPES @@ -71,7 +73,7 @@ (add-algo {:name "moon" :comment "very good - 2:1" - :algo moon-signal + :algo moon-study :charts [;nil ; {:trade "flags"} ;{:trade "chars" #_"arrows"} {:signal-text {:type "chars" @@ -84,3 +86,52 @@ :options {:symbol "SPY" :frequency "D"}}) + +(comment + + (require '[ta.helper.date :refer [parse-date]]) + (def ds + (tc/dataset [{:date (parse-date "2023-01-01") + :b 2 + :c 3} + {:date (parse-date "2023-01-01") + :b 5 + :c 6}])) + + (def phase (moon-phase (:date ds))) + (def signal (moon-signal phase)) + (def ds-demo (tc/add-columns + ds + {:phase phase + :signal signal}) + ) + + (require '[ta.warehouse :as wh]) + (require '[ta.data.settings :refer [determine-wh]]) + (require '[tablecloth.api :as tc]) + + (def w (determine-wh "GOOGL")) + (def ds-bars (wh/load-symbol :stocks "D" "SPY")) + (tc/info ds-bars) + + (require '[ta.backtest.signal :refer [trade-signal]]) + (require '[ta.backtest.roundtrip-backtest :refer [calc-roundtrips]]) + (trade-signal ds-demo) + + (-> (trade-signal ds-demo) + (calc-roundtrips {}) + ) + + (trade-signal ds-bars) + + + + (am/algo-run "moon" {:symbol "SPY" :frequency "D"}) + (am/algo-run "moon" {:symbol "GOOGL" :frequency "D"}) + + + + ; + ) + + diff --git a/app/demo/src/demo/goldly/page/tvalgo.cljs b/app/demo/src/demo/goldly/page/tvalgo.cljs index 41d29cee..edd9459a 100644 --- a/app/demo/src/demo/goldly/page/tvalgo.cljs +++ b/app/demo/src/demo/goldly/page/tvalgo.cljs @@ -16,91 +16,48 @@ ;; symbol/algo switcher -(defonce algo-state +(defonce menu-ctx (r/atom {:algos [] :symbols ["TLT" "SPY" "QQQ" "EURUSD" "RIVN" "GOOGL" "FCEL" "NKLA" "INTC" "FRC" "AMZN" "WFC" "PLTR" "BZ0" "NG0" "RB0" "ZC0" "MES0" "M2K0" "MNQ0" "MYM0" ]})) -(run-a algo-state [:algos] +(run-a menu-ctx [:algos] 'ta.algo.manager/algo-names) ; get once the names of all available algos (defn algo-info [algo] (let [algo-loaded (r/atom nil)] (when algo (when-not (= @algo-loaded algo) - (run-a algo-state [:algoinfo] 'ta.algo.manager/algo-info algo) + (run-a menu-ctx [:algoinfo] 'ta.algo.manager/algo-info algo) nil)))) - -(defn tradingview-modifier [symbol _frequency] - (let [symbol-showing (r/atom symbol)] - (fn [symbol frequency] - (when-not (= symbol @symbol-showing) - (reset! symbol-showing symbol) - (.log js/console "tv symbol change detected!") - ;(set-symbol symbol frequency) - nil)))) - -(defn algo-modifier [_algo algoinfo] - (let [showing (r/atom algoinfo)] - (fn [algo algoinfo] - (when-let [charts (:charts algoinfo)] - (when (> (count charts) 0) - (when-not (= algoinfo @showing) - (reset! showing algoinfo) - (println "TV ALGO CHANGED TO: " algo " charts: " charts) - ;(set! (.-datafeed @tv-widget-atom) (tradingview-algo-feed algo)) - ;(set! (-> js/window .-widget .-datafeed) (tradingview-algo-feed algo)) - ;(set! (.-text obj) text) - ;Object.getPrototypeOf (widget) .datafeed - ;(set! (.-datafeed - ; (.getPrototypeOf js/Object js/widget)) - ;(js/setTimeout #(add-algo-studies charts) 300) - ; (js/setTimeout #(track-range) 300) - ;(add-algo-studies charts) - nil)))))) - -#_(defn tv-status [] - (fn [] - [: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) [])} + :items (or (:algos @menu-ctx) [])} algo-input [:algo]] [input/select {:nav? false - :items (:symbols @algo-state)} + :items (:symbols @menu-ctx)} 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 algo-ui [] (fn [] - (let [{:keys [_algos algo algoinfo]} @algo-state] + (let [{:keys [_algos algo algoinfo]} @menu-ctx] [:div.flex.flex-col.h-full.w-full [algo-menu] [algo-info algo] - ;[tradingview-modifier symbol frequency] - ;[algo-modifier algo algoinfo] [:div.h-full.w-full - [tradingview-algo algo-ctx] - ] - -;[page-renderer data page] - ]))) + [tradingview-algo algo-ctx]]]))) (defn tvalgo-page [_route] [:div.h-screen.w-screen.bg-red-500 diff --git a/app/resources/symbollist/equity-style.edn b/app/resources/symbollist/equity-style.edn index d06655aa..90c01e63 100644 --- a/app/resources/symbollist/equity-style.edn +++ b/app/resources/symbollist/equity-style.edn @@ -21,7 +21,7 @@ ;Large-Cap All ;{:cap :large :style :all :name "Diamond Trust Series 1" :symbol "DIA"} - ;{:cap :large :style :all :name "NASDAQ 100 Index Tracking Stock" :symbol "QQQ"} + {:cap :large :style :all :name "NASDAQ 100 Index Tracking Stock" :symbol "QQQ"} ;{:cap :large :style :all :name "IShares S&P 100" :symbol "OEF"} {:cap :large :style :all :name "IShares S&P 500" :symbol "IVV" :category :etf} ;{:cap :large :style :all :name "IShares NYSE 100" :symbol "NY"} diff --git a/app/resources/symbollist/test.edn b/app/resources/symbollist/test.edn index 7f8539ea..cb42923b 100644 --- a/app/resources/symbollist/test.edn +++ b/app/resources/symbollist/test.edn @@ -1,8 +1,8 @@ -[{:symbol "QQQ" :name "nasdaq" :category :etf} - {:symbol "MSFT" :name "Microsoft" :category :equity} +[{:symbol "MSFT" :name "Microsoft" :category :equity} {:symbol "XOM" :name "Exxon Mobile" :category :equity} {:symbol "AMZN" :name "Amazon" :category :equity} {:symbol "GOOG" :name "Google" :category :equity} + {:symbol "GOOGL" :name "Google" :category :equity} {:symbol "TSLA" :name "Tesla" :category :equity} {:symbol "SPY" :name "S&P 500" :category :etf} {:symbol "DEMO" :name2 "intentionally missing name (name2)" :category :wild} diff --git a/lib/astro/src/astro/marks.clj b/lib/astro/src/astro/marks.clj index 0abfe5fa..470e7316 100644 --- a/lib/astro/src/astro/marks.clj +++ b/lib/astro/src/astro/marks.clj @@ -126,8 +126,9 @@ (defn moon-aspect? [{:keys [a b] :as aspect}] (or (= a :Moon) (= b :Moon))) -(defn astro-marks [symbol resolution options from to] - (let [aspects (load-aspects symbol resolution options from to) +(defn astro-marks [options from to] + (let [{:keys [symbol frequency]} options + aspects (load-aspects symbol frequency options from to) aspects (if (:show-moon options) aspects (remove moon-aspect? aspects))] diff --git a/lib/helper/src/ta/helper/ago.clj b/lib/helper/src/ta/helper/ago.clj index 5267a164..b92db33b 100644 --- a/lib/helper/src/ta/helper/ago.clj +++ b/lib/helper/src/ta/helper/ago.clj @@ -36,7 +36,8 @@ (xf result))))) (defn xf-future [xf] - (let [first (atom true)] + (let [first (atom true) + last (atom nil)] (fn ;; SET-UP ([] @@ -44,6 +45,8 @@ (xf)) ;; PROCESS ([result input] + (when-not (nil? input) + (reset! last input)) (if @first (do (reset! first false) result) ; unchanged collection for first element @@ -52,7 +55,7 @@ ;; TEAR-DOWN ([result] (when-not @first - (xf result nil)) + (xf result @last)) (xf result))))) @@ -68,5 +71,6 @@ (into [] xf-ago-pair [3 4 5 6 7]) (into [] xf-future [3 4 5 6 7]) + (into [] xf-future [4 5 6]) ; ) diff --git a/lib/tradingview/src/ta/tradingview/goldly/algo/interaction.cljs b/lib/tradingview/src/ta/tradingview/goldly/algo/interaction.cljs index 4b901960..47319d3d 100644 --- a/lib/tradingview/src/ta/tradingview/goldly/algo/interaction.cljs +++ b/lib/tradingview/src/ta/tradingview/goldly/algo/interaction.cljs @@ -142,11 +142,16 @@ (when (or symbol-changed algo-changed) (println "resetting algo-ctx data..") (c/set-algo-data algo-ctx nil) - (i/reset-data tv) - (c/set-cache-needed) + ;(i/reset-data tv) + ;(c/set-cache-needed) (println "switching tv symbol..") - (i/set-symbol tv symbol frequency (fn [modus opts] - (on-load-finished algo-ctx tv modus opts) + (i/set-symbol tv symbol "1D" #_frequency (fn [modus opts] + (println "ON-SET-SYMBOL FINISHED: modus: " modus " opts: " opts) + (let [modus nil + opts nil] + (on-load-finished algo-ctx tv modus opts) + ) + ))) nil)) diff --git a/lib/tradingview/src/ta/tradingview/goldly/feed/algo2.cljs b/lib/tradingview/src/ta/tradingview/goldly/feed/algo2.cljs index 4d2256d9..27d1caff 100644 --- a/lib/tradingview/src/ta/tradingview/goldly/feed/algo2.cljs +++ b/lib/tradingview/src/ta/tradingview/goldly/feed/algo2.cljs @@ -20,8 +20,6 @@ (into []) (clj->js))) - - (defn get-algo-full [algo-ctx] (let [{:keys [algo opts]} (c/get-algo-input algo-ctx) _ (println "get-algo-full algo: " algo "symbol: " (:symbol opts)) @@ -97,42 +95,44 @@ ;(println "tradingview-algo-feed setup ..") (clj->js {:onReady (fn [onConfigCallback] - (let [cb (fn [[_ data]] ; _ = event-type - (let [{:keys [result _error]} data - result-js (clj->js result)] - ;(println "TV CONFIG: " result) - (onConfigCallback result-js)))] - ;(println "TV/CONFIG..") - (run-cb {:fun 'ta.tradingview.handler-datasource/get-server-config - :args {} - :cb cb}))) + (let [rp (clj 'ta.tradingview.handler-datasource/get-server-config)] + (-> rp + (p/then (fn [result] + (println "TV CONFIG: " result) + (onConfigCallback (clj->js result)))) + (p/catch (fn [err] + (println "TV CONFIG ERROR: " err))) + ))) + :searchSymbols (fn [userInput exchange symbolType onResultReadyCallback] - ;(println "TV/SEARCH " userInput exchange symbolType) (let [query userInput type symbolType limit 10 - cb (fn [[_ data]] ; _ = event-type - (let [{:keys [result _error]} data - result-js (clj->js result)] - ;(println "TV SYMBOL SEARCH: " result) - (onResultReadyCallback result-js)))] - (run-cb {:fun 'ta.tradingview.handler-datasource/symbol-search - :args [query type exchange limit] - :cb cb}))) - :resolveSymbol (fn [symbolName onSymbolResolvedCallback _onResolveErrorCallback] - ;(println "TV/resolve symbol" symbolName) - (let [cb (fn [[_ data]] ; _ = event-type - (let [{:keys [result _error]} data - result-js (clj->js result)] - ;(println "TV SYMBOL INFO: " result) - (onSymbolResolvedCallback result-js)))] - (run-cb {:fun 'ta.tradingview.handler-datasource/symbol-info - :args [symbolName] ; {:symbol symbolName} - :cb cb}))) + rp (clj 'ta.tradingview.handler-datasource/symbol-search query type exchange limit)] + (-> rp + (p/then (fn [result] + (onResultReadyCallback (clj->js result)))) + (p/catch (fn [err] + (println "TV SEARCH error: " err)))))) + + :resolveSymbol (fn [symbolName onSymbolResolvedCallback onResolveErrorCallback] + (println "TV/resolve symbol" symbolName) + (let [rp (clj 'ta.tradingview.handler-datasource/symbol-info symbolName)] + (-> rp + (p/then (fn [result] + (println "TV SYMBOL RESOLVED: " result) + (onSymbolResolvedCallback (clj->js result)))) + (p/catch (fn [err] + (println "TV RESOLVE SYMBOL error: " err) + (onResolveErrorCallback (clj->js err))))))) + + :getBars (fn [_symbolInfo _resolution period onHistoryCallback onErrorCallback] (let [period-clj (extract-period period)] (get-bars algo-ctx period-clj onHistoryCallback onErrorCallback) nil)) + + :subscribeBars (fn [symbolInfo resolution _onRealtimeCallback subscribeUID onResetCacheNeededCallback] (println "subscribe-bars: " symbolInfo resolution subscribeUID) (add-watch c/need-cache-reset-atom :cache-reset @@ -141,11 +141,10 @@ (println "triggering reset-cache-needed") (reset! c/need-cache-reset-atom false) (onResetCacheNeededCallback)))) - - ) + nil) :unsubscribeBars (fn [subscriberUID] - (println "unsubscribe-bars: " subscriberUID) - ) + (println "unsubscribe-bars: " subscriberUID)) + :getServerTime (fn [onTimeCallback] (let [rp (clj 'ta.tradingview.handler-datasource/server-time)] (p/then rp (fn [time] @@ -157,30 +156,28 @@ :calculateHistoryDepth (fn [resolution resolutionBack intervalBack] (println "calculate history depth:" resolution resolutionBack intervalBack)) - :getMarks (fn [symbolInfo startDate endDate onDataCallback resolution] + :getMarks (fn [symbolInfo epoch-start epoch-end onDataCallback resolution] (let [;period-clj (extract-period period) - epoch-start startDate ; (:from period-clj) - epoch-end endDate ; (:to period-clj) - frequency (if (= resolution "1D") - "D" - resolution) - symbol-info-clj (js->clj symbolInfo :keywordize-keys true) - symbol (:ticker symbol-info-clj) - ;{:keys [algo options]} (get-algo-and-options) - cb (fn [[_ data]] ; _ = event-type - (let [{:keys [result _error]} data - result-js (clj->js result)] - ;(println "TV MARKS: " result) - (onDataCallback result-js)))] - ;(println "TV MARKS: algo" algo symbol startDate endDate frequency) - #_(run-cb {:fun 'ta.algo.manager/algo-marks - :args [algo symbol frequency options epoch-start epoch-end] - :cb cb}) - (onDataCallback (clj->js [])) + ; frequency (if (= resolution "1D") "D" resolution) + ;symbol-info-clj (js->clj symbolInfo :keywordize-keys true) + ;symbol (:ticker symbol-info-clj) + {:keys [algo opts]} (c/get-algo-input algo-ctx) + rp (clj 'ta.algo.manager/algo-marks algo opts epoch-start epoch-end)] + (-> rp + (p/then (fn [result] + (println "MARKS RESULT: " result) + ;(onDataCallback (clj->js [])) + (onDataCallback (clj->js result)))) + (p/catch (fn [err] + (println "ERROR GETTING MARKS: " err)))) + nil )) + :getTimeScaleMarks (fn [symbolInfo startDate endDate _onDataCallback resolution] + (println "**GET-TIMESCALE-MARKS**") ;(println "get-timescale-marks" symbolInfo startDate endDate resolution) ) + :about "algo-feed"})) diff --git a/lib/tradingview/src/ta/tradingview/goldly/tradingview.cljs b/lib/tradingview/src/ta/tradingview/goldly/tradingview.cljs index f3586032..f04c60c0 100644 --- a/lib/tradingview/src/ta/tradingview/goldly/tradingview.cljs +++ b/lib/tradingview/src/ta/tradingview/goldly/tradingview.cljs @@ -39,7 +39,7 @@ ;"tick_resolution" ; Enables the support of tick resolution ;"secondary_series_extend_time_scale" ; Enables a feature to allow an additional series to extend the time scale ;"cl_feed_return_all_data" ;Allows you to return more bars from the data feed than requested and displays it on a chart simultaneously - ;"same_data_requery" ;Allows you to call setSymbol with the same symbol to refresh the data + "same_data_requery" ;Allows you to call setSymbol with the same symbol to refresh the data ;"high_density_bars" ;Allows zooming out to show more than 60000 bars on a single screen ;"cropped_tick_marks" @@ -92,7 +92,7 @@ :allow_symbol_change true :left_toolbar false - ; "withdateranges" true + "withdateranges" true "range" "12M" "time_frames" [{:text "100y" :resolution "1D" :description "All" :title "All"} {:text "50y" :resolution "6M" :description "50 Years" } diff --git a/lib/tradingview/src/ta/tradingview/handler_datasource.clj b/lib/tradingview/src/ta/tradingview/handler_datasource.clj index 881c4e30..d22b2945 100644 --- a/lib/tradingview/src/ta/tradingview/handler_datasource.clj +++ b/lib/tradingview/src/ta/tradingview/handler_datasource.clj @@ -65,10 +65,12 @@ ;{:value "LN" :name "London" :desc ""} ]}) -(defn get-server-config [] +(defn get-server-config [] + ; used by websocket server-config) (defn config-handler [_] + ; used by udf (info "tv/config") (res/response server-config)) diff --git a/lib/trateg/deps.edn b/lib/trateg/deps.edn index 911c721a..d0b7f234 100644 --- a/lib/trateg/deps.edn +++ b/lib/trateg/deps.edn @@ -10,6 +10,7 @@ org.ta4j/ta4j-core {:mvn/version "0.14"} ; ta4j java technical indicator library org.clojure/algo.generic {:mvn/version "0.1.3"} generateme/fastmath {:mvn/version "2.1.8"} + try-let/try-let {:mvn/version "1.3.1"} ; com.stuartsierra/frequencies {:mvn/version "0.1.0"} ; percentile stats ta/warehouse {:local/root "../warehouse" :deps/manifest :deps} ta/data {:local/root "../data" :deps/manifest :deps} diff --git a/lib/trateg/src/ta/algo/manager.clj b/lib/trateg/src/ta/algo/manager.clj index e9da118f..8bd03050 100644 --- a/lib/trateg/src/ta/algo/manager.clj +++ b/lib/trateg/src/ta/algo/manager.clj @@ -1,5 +1,6 @@ (ns ta.algo.manager (:require + [taoensso.timbre :refer [trace debug info warnf error]] [tech.v3.datatype :as dtype] [tech.v3.dataset :as tds] [tablecloth.api :as tc] @@ -27,7 +28,7 @@ (get @algos name)) (defn algo-info [name] - (if-let [algo (get-algo name)] + (when-let [algo (get-algo name)] (let [charts (or (:charts algo) []) options (or (:options algo) {})] (-> algo @@ -97,12 +98,12 @@ ; -(defn algo-run [name user-options] - (if-let [{:keys [algo options charts]} (get-algo name)] +(defn algo-run [algo-name user-options] + (if-let [{:keys [algo options charts]} (get-algo algo-name)] (let [options (merge options user-options) {:keys [ds-study ds-roundtrips] :as backtest} (run-backtest algo options)] (merge - {:name name + {:name algo-name :options options :charts charts :study-extra-cols (study-extra-cols ds-study)} @@ -114,7 +115,7 @@ {:highchart (highchart ds-study (:axes-spec options))} ; {}) )) - {:name name + {:name algo-name :error "Algo not found."})) (defn epoch @@ -164,14 +165,14 @@ (let [ds (algo-run-window name symbol frequency options epoch-start epoch-end)] (ds->map ds))) -(defn algo-marks [name symbol frequency user-options epoch-start epoch-end] - (if-let [{:keys [marks options]} (get-algo name)] +(defn algo-marks [algo-name user-options epoch-start epoch-end] + (if-let [{:keys [marks options]} (get-algo algo-name)] (if marks (let [options (merge options user-options)] - (marks symbol frequency options epoch-start epoch-end)) - (do (println "NO MARKS - " name "does not define a marks fn.") + (marks symbol options epoch-start epoch-end)) + (do (info "NO MARKS - " algo-name "does not define a marks fn.") [])) - (do (println "NO MARKS - algo not found: " name) + (do (info "NO MARKS - algo not found: " algo-name) []))) (defn algo-shapes [algo-name user-options epoch-start epoch-end] @@ -179,11 +180,11 @@ (if shapes (let [options (merge options user-options) data (shapes options epoch-start epoch-end)] - (println "SHAPE [" (count data) "]" algo-name (:symbol options) epoch-start epoch-end) + (info "SHAPE [" (count data) "]" algo-name (:symbol options) epoch-start epoch-end) data) - (do (println "NO SHAPES - " algo-name "does not define a shapes fn.") + (do (info "NO SHAPES - " algo-name "does not define a shapes fn.") [])) - (do (println "NO SHAPES - algo not found: " algo-name) + (do (info "NO SHAPES - algo not found: " algo-name) []))) (comment @@ -221,6 +222,29 @@ (-> (algo-shapes "moon" "SPY" "D" {:show-moon true} epoch-start epoch-end) ;count ) + + (algo-run-browser "moon" {:symbol "SPY" :frequency "D"}) + + + (algo-run-browser "moon" {:symbol "GOOGL" :frequency "D"}) + (algo-run "moon" {:symbol "GOOGL" :frequency "D"}) + (run-backtest "moon" {:symbol "GOOGL" :frequency "D"}) + + + + + (require '[ta.warehouse :as wh]) + (require ' [ta.backtest.signal :refer [trade-signal]]) + (let [ds-bars (wh/load-symbol :stocks "D" "GOOGL") + {:keys [algo]} (get-algo "moon") + ds-algo (algo ds-bars {:symbol "GOOGL" :frequency "D"})] + + (trade-signal ds-algo) + + ) + + + (->> ;(algo-run an {:symbol "SPY"}) (algo-run-browser an {:symbol "TLT"}) ; :stats diff --git a/lib/trateg/src/ta/backtest/roundtrip_backtest.clj b/lib/trateg/src/ta/backtest/roundtrip_backtest.clj index 4d2e1b16..d297e4ce 100644 --- a/lib/trateg/src/ta/backtest/roundtrip_backtest.clj +++ b/lib/trateg/src/ta/backtest/roundtrip_backtest.clj @@ -1,5 +1,6 @@ (ns ta.backtest.roundtrip-backtest (:require + [taoensso.timbre :refer [trace debug info warnf error]] [tech.v3.datatype :as dtype] [tech.v3.datatype.functional :as fun] [tablecloth.api :as tc] @@ -7,7 +8,10 @@ [ta.data.settings :refer [determine-wh ]] [ta.helper.ago :refer [xf-future]] [ta.backtest.signal :refer [trade-signal]] - [ta.backtest.position-pl :refer [position-pl]])) + [ta.backtest.position-pl :refer [position-pl]] + [clojure.edn :as edn] + [try-let :refer [try-let]] + )) (defn- bar->roundtrip-partial [ds] @@ -32,6 +36,17 @@ (> chg-p 0) false)) +(defn isNaN [x] + (== ##NaN x)) + + +(defn get-last-not-nil [ds kw] + (let [vec (get ds kw) + vec-no-nil (remove nil? vec)] + (last vec-no-nil))) + +; (get-last-nan {:close [1 2 3 nil]} :close) + (defn aggregate-bars-to-roundtrip [{:keys [entry-cols] :or {entry-cols []}} ds] ;(println "agg with rows: " (tc/row-count ds)) @@ -40,9 +55,9 @@ :date-open (->> ds :date-open first) :price-open (->> ds :price-open first) ; close - :index-close (->> ds :index-close last) - :date-close (->> ds :date-close last) - :price-close (->> ds :price-close last) + :index-close (get-last-not-nil ds :index-close) + :date-close (get-last-not-nil ds :date-close) + :price-close (get-last-not-nil ds :price-close) ; trade :position (->> ds :position first) :bars (->> ds :index-open count) @@ -103,18 +118,34 @@ ; ) +(defn calc-study [algo ds-bars algo-options] + (algo ds-bars algo-options)) + + (defn backtest-ds "algo has to create :position column creates roundtrips based on this column" [ds-bars algo options] - (let [algo-options (dissoc options :w :symbol :frequency :entry-cols) - ds-study (-> ds-bars - (algo algo-options) - trade-signal)] - (if (:signal ds-study) - {:ds-study ds-study - :ds-roundtrips (calc-roundtrips ds-study options)} - {:ds-study ds-study}))) + (try-let [algo-options (dissoc options :w :symbol :frequency :entry-cols) + ds-study (calc-study algo ds-bars algo-options)] + (if (:signal ds-study) + (try-let [ds-study-position (trade-signal ds-study) + roundtrips (calc-roundtrips ds-study-position options)] + {:ds-study ds-study-position + :ds-roundtrips roundtrips} + (catch Exception e + (error "backtest-ds exception in rountrip-calculation: " e) + {:error "backtest roundtrip calculation exception" + :ds-study ds-study})) + ; the algo is not setup to calculate :signal olumn + {:ds-study ds-study}) + (catch Exception e + (error "exception in calculating study: " e) + {:ds-study ds-bars + :error "could not calculate study"}))) + + + (defn run-backtest "algo has to create :position column @@ -138,3 +169,11 @@ r)))) +(comment + + (determine-wh "GOOGL") + (wh/load-symbol :stocks "D" "GOOGL") + + ; + ) +