diff --git a/lib/calendar/dev/src/dev/calendar_helper.clj b/lib/calendar/dev/src/dev/calendar_helper.clj index a886b8cb..e0719a88 100644 --- a/lib/calendar/dev/src/dev/calendar_helper.clj +++ b/lib/calendar/dev/src/dev/calendar_helper.clj @@ -21,8 +21,5 @@ (time-open? (:us calendars) (to-utc "2024-10-11T16:00:00")) -;=> false +;=> true (time-open? (:us calendars) (t/instant)) - -(t/time (to-utc "2024-10-11T16:00:00")) -(t/time (t/instant)) diff --git a/lib/calendar/dev/src/dev/calendar_seq.clj b/lib/calendar/dev/src/dev/calendar_seq.clj index a3798a65..18f6e17f 100644 --- a/lib/calendar/dev/src/dev/calendar_seq.clj +++ b/lib/calendar/dev/src/dev/calendar_seq.clj @@ -1,11 +1,8 @@ (ns dev.calendar-seq (:require [tick.core :as t] - [quanta.calendar.core :refer [trailing-window calendar-seq calendar-seq-prior - fixed-window - close->open-dt open->close-dt]] - [ta.calendar.calendars :refer [calendars]] - [dev.utils :refer [to-utc]])) + [quanta.calendar.core :refer [calendar-seq calendar-seq-prior calendar-seq-prior-open + fixed-window-open fixed-window]])) (->> (t/in (t/date-time "2024-10-01T16:20:00") "America/New_York") @@ -110,4 +107,113 @@ (->> (t/in (t/date-time "2024-10-01T23:59:59.999999999") "UTC") (calendar-seq-prior [:crypto :d]) - (take 20)) \ No newline at end of file + (take 10)) +;=> +;(#time/zoned-date-time"2024-10-01T23:59:59.999999999Z[UTC]" +; #time/zoned-date-time"2024-09-30T23:59:59.999999999Z[UTC]" +; #time/zoned-date-time"2024-09-29T23:59:59.999999999Z[UTC]" +; #time/zoned-date-time"2024-09-28T23:59:59.999999999Z[UTC]" +; #time/zoned-date-time"2024-09-27T23:59:59.999999999Z[UTC]" +; #time/zoned-date-time"2024-09-26T23:59:59.999999999Z[UTC]" +; #time/zoned-date-time"2024-09-25T23:59:59.999999999Z[UTC]" +; #time/zoned-date-time"2024-09-24T23:59:59.999999999Z[UTC]" +; #time/zoned-date-time"2024-09-23T23:59:59.999999999Z[UTC]" +; #time/zoned-date-time"2024-09-22T23:59:59.999999999Z[UTC]") + + +(-> (fixed-window [:crypto :h] {:start (t/instant "2024-01-01T01:00:00Z") + :end (t/instant "2024-01-01T23:59:59.999999999Z")}) + count) +; => 24 + +(-> (fixed-window [:crypto :h] {:start (t/instant "2024-01-01T01:00:00Z") + :end (t/instant "2024-01-01T23:00:00Z")}) + count) +; => 23 + + +(-> (fixed-window [:crypto :d] {:start (t/instant "2024-01-01T23:59:59.999999999Z") + :end (t/instant "2024-01-07T23:59:59.999999999Z")})) +;=> +;(#time/zoned-date-time"2024-01-07T23:59:59.999999999Z[UTC]" +; #time/zoned-date-time"2024-01-06T23:59:59.999999999Z[UTC]" +; #time/zoned-date-time"2024-01-05T23:59:59.999999999Z[UTC]" +; #time/zoned-date-time"2024-01-04T23:59:59.999999999Z[UTC]" +; #time/zoned-date-time"2024-01-03T23:59:59.999999999Z[UTC]" +; #time/zoned-date-time"2024-01-02T23:59:59.999999999Z[UTC]" +; #time/zoned-date-time"2024-01-01T23:59:59.999999999Z[UTC]") + +(-> (fixed-window-open [:crypto :d] {:start (t/instant "2024-09-01T00:00:00Z") + :end (t/instant "2024-09-08T00:00:00Z")})) +;=> +;(#time/zoned-date-time"2024-09-08T00:00Z[UTC]" +; #time/zoned-date-time"2024-09-07T00:00Z[UTC]" +; #time/zoned-date-time"2024-09-06T00:00Z[UTC]" +; #time/zoned-date-time"2024-09-05T00:00Z[UTC]" +; #time/zoned-date-time"2024-09-04T00:00Z[UTC]" +; #time/zoned-date-time"2024-09-03T00:00Z[UTC]" +; #time/zoned-date-time"2024-09-02T00:00Z[UTC]" +; #time/zoned-date-time"2024-09-01T00:00Z[UTC]") + +(-> (fixed-window-open [:crypto :d] {:start (t/instant "2024-01-01T23:59:59.999999999Z") + :end (t/instant "2024-01-05T23:59:59.999999999Z")})) +; NOTE: start is not valid bar open time. +;=> +;(#time/zoned-date-time"2024-01-05T00:00Z[UTC]" +; #time/zoned-date-time"2024-01-04T00:00Z[UTC]" +; #time/zoned-date-time"2024-01-03T00:00Z[UTC]" +; #time/zoned-date-time"2024-01-02T00:00Z[UTC]") + +(-> (fixed-window [:crypto :h] {:start (t/instant "2024-01-01T23:59:59.999999999Z") + :end (t/instant "2024-01-02T23:59:59.999999999Z")})) +;=> +;(#time/zoned-date-time"2024-01-02T23:59:59.999999999Z[UTC]" +; #time/zoned-date-time"2024-01-02T23:00Z[UTC]" +; #time/zoned-date-time"2024-01-02T22:00Z[UTC]" +; #time/zoned-date-time"2024-01-02T21:00Z[UTC]" +; #time/zoned-date-time"2024-01-02T20:00Z[UTC]" +; #time/zoned-date-time"2024-01-02T19:00Z[UTC]" +; #time/zoned-date-time"2024-01-02T18:00Z[UTC]" +; #time/zoned-date-time"2024-01-02T17:00Z[UTC]" +; #time/zoned-date-time"2024-01-02T16:00Z[UTC]" +; #time/zoned-date-time"2024-01-02T15:00Z[UTC]" +; #time/zoned-date-time"2024-01-02T14:00Z[UTC]" +; #time/zoned-date-time"2024-01-02T13:00Z[UTC]" +; #time/zoned-date-time"2024-01-02T12:00Z[UTC]" +; #time/zoned-date-time"2024-01-02T11:00Z[UTC]" +; #time/zoned-date-time"2024-01-02T10:00Z[UTC]" +; #time/zoned-date-time"2024-01-02T09:00Z[UTC]" +; #time/zoned-date-time"2024-01-02T08:00Z[UTC]" +; #time/zoned-date-time"2024-01-02T07:00Z[UTC]" +; #time/zoned-date-time"2024-01-02T06:00Z[UTC]" +; #time/zoned-date-time"2024-01-02T05:00Z[UTC]" +; #time/zoned-date-time"2024-01-02T04:00Z[UTC]" +; #time/zoned-date-time"2024-01-02T03:00Z[UTC]" +; #time/zoned-date-time"2024-01-02T02:00Z[UTC]" +; #time/zoned-date-time"2024-01-02T01:00Z[UTC]" +; #time/zoned-date-time"2024-01-01T23:59:59.999999999Z[UTC]") + + +(->> (calendar-seq-prior [:crypto :d] (t/instant "2024-01-02T23:59:59.999999999Z")) + (take 1)) +; => (#time/zoned-date-time"2024-01-02T23:59:59.999999999Z[UTC]") + +(->> (t/in (t/date-time "2024-09-08T00:00:00") "UTC") + (calendar-seq-prior-open [:crypto :d]) + (take 1)) +;=> (#time/zoned-date-time"2024-09-08T00:00Z[UTC]") + +(->> (t/in (t/date-time "2024-01-02T23:59:59.999999999") "UTC") + (calendar-seq-prior-open [:crypto :d]) + (take 1)) +;=> (#time/zoned-date-time"2024-01-02T00:00Z[UTC]") + +(fixed-window-open [:crypto :d] {:start (t/in (t/date-time "2024-02-05T23:59:59.999999999") "UTC") + :end (t/in (t/date-time "2024-02-11T23:59:59.999999999") "UTC")}) +;=> +;(#time/zoned-date-time"2024-02-11T00:00Z[UTC]" +; #time/zoned-date-time"2024-02-10T00:00Z[UTC]" +; #time/zoned-date-time"2024-02-09T00:00Z[UTC]" +; #time/zoned-date-time"2024-02-08T00:00Z[UTC]" +; #time/zoned-date-time"2024-02-07T00:00Z[UTC]" +; #time/zoned-date-time"2024-02-06T00:00Z[UTC]") diff --git a/lib/calendar/dev/src/dev/core.clj b/lib/calendar/dev/src/dev/core.clj index bde18819..7cf19d68 100644 --- a/lib/calendar/dev/src/dev/core.clj +++ b/lib/calendar/dev/src/dev/core.clj @@ -3,8 +3,8 @@ [tick.core :as t] [ta.calendar.calendars :refer [calendars]] [ta.calendar.interval :refer [intervals]] - [quanta.calendar.core :refer [next-close current-close close->open-dt open->close-dt current-close2]] - [dev.utils :refer [to-utc]])) + [ta.calendar.helper :refer [trading-open-time]] + [quanta.calendar.core :refer [next-close current-close]])) (current-close [:crypto :m] (t/in (t/date-time "2024-02-08T23:59:30") "UTC")) @@ -77,4 +77,33 @@ :next-close-dt next-close-dt :next-close-instant next-close-instant}) -(t/instant) +(let [dt-str "2024-02-08T23:59:59.999999999" + inst (-> (str dt-str "Z") (t/instant)) + utc (t/in (t/date-time dt-str) "UTC")] + {:inst inst + :utc utc}) + +(t/date (t/instant "2024-02-08T23:59:59.999999999")) + +(let [calendar (:crypto calendars) + interval (:d intervals) + current-close-dt (:current-close interval)] + (current-close-dt calendar (t/in (t/date-time "2024-02-08T23:59:59.999999999") "UTC"))) +;=> #time/zoned-date-time"2024-02-08T23:59:59.999999999Z[UTC]" + +(let [calendar (:crypto calendars) + interval (:d intervals) + current-open-dt (:current-open interval)] + (current-open-dt calendar (t/in (t/date-time "2024-02-08T23:59:59.999999999") "UTC"))) +; => #time/zoned-date-time"2024-02-08T00:00Z[UTC]" + +(let [t (t/instant "2024-02-08T23:59:59.999999999Z")] + (trading-open-time (:crypto calendars) t)) +;=> #time/zoned-date-time"2024-02-08T00:00Z[UTC]" + + +(let [calendar (:crypto calendars) + interval (:h4 intervals) + current-close-dt (:current-close interval)] + (current-close-dt calendar (t/in (t/date-time "2024-02-10T12:00:00") "UTC"))) +; => #time/zoned-date-time"2024-02-10T12:00Z[UTC]" \ No newline at end of file diff --git a/lib/calendar/dev/src/dev/date.clj b/lib/calendar/dev/src/dev/date.clj new file mode 100644 index 00000000..77d79652 --- /dev/null +++ b/lib/calendar/dev/src/dev/date.clj @@ -0,0 +1,51 @@ +(ns dev.date + (:require + [tick.core :as t] + [ta.helper.date :as d])) + +; !!!!! LOCAL timezone is used + +(t/date (t/instant "2024-02-08T23:59:59.999999999Z")) +;=> #time/date"2024-02-08" +(t/date (t/instant "2024-02-08T00:00:00Z")) +;=> #time/date"2024-02-07" + +(t/in (t/date-time (t/instant "2024-02-08T00:00:00Z")) "UTC") +;=> #time/zoned-date-time"2024-02-07T19:00Z[UTC]" + +(t/date (t/zoned-date-time (t/instant "2024-02-08T00:00:00Z"))) +;=> #time/date"2024-02-07" + +(t/zoned-date-time (t/instant "2024-02-08T00:00:00Z")) +;=> #time/zoned-date-time"2024-02-07T21:00-05:00" + +(t/date (t/zoned-date-time (t/instant "2024-02-08T00:00:00Z"))) +; => #time/date"2024-02-07" + +; +; CORRECT timezone +; +(t/in (t/instant "2024-02-08T00:00:00Z") "America/New_York") +; => #time/zoned-date-time"2024-02-07T19:00-05:00[America/New_York]" + +(t/in (t/instant "2024-02-08T00:00:00Z") "UTC") +; => #time/zoned-date-time"2024-02-08T00:00Z[UTC]" + +(t/date (t/zoned-date-time "2024-02-08T00:00:00Z")) +; => #time/date"2024-02-08" + + +(t/day-of-month (t/instant "2024-02-08T23:59:59.999999999Z")) +(t/year (t/instant "2024-02-08T23:59:59.999999999Z")) +(t/year-month (t/instant "2024-02-08T23:59:59.999999999Z")) + +(t/last-day-of-month (t/in (t/instant "2024-02-08T00:00:00Z") "UTC")) + +(t/day-of-week (t/instant "2024-02-08T00:00:00Z")) + + +(t/date? (t/date (t/zoned-date-time "2024-02-08T00:00:00Z"))) +(t/date-time? (t/zoned-date-time "2024-02-08T00:00:00Z")) +(t/zoned-date-time? (t/zoned-date-time "2024-02-08T00:00:00Z")) + +(t/at (t/date (t/in (t/instant "2024-02-08T00:00:00Z") "UTC")) (t/new-time 12 00)) diff --git a/lib/calendar/src/ta/calendar/interval/day.clj b/lib/calendar/src/ta/calendar/interval/day.clj index 508e6a07..e1ee427c 100644 --- a/lib/calendar/src/ta/calendar/interval/day.clj +++ b/lib/calendar/src/ta/calendar/interval/day.clj @@ -1,8 +1,8 @@ (ns ta.calendar.interval.day (:require - [tick.core :as t] - [ta.helper.date :refer [at-time]] - [ta.calendar.helper :refer [before-trading-hours? after-trading-hours? + [tick.core :as t] + [ta.helper.date :refer [at-time]] + [ta.calendar.helper :refer [before-trading-hours? after-trading-hours? trading-open-time trading-close-time day-open? day-with-open? day-with-close? diff --git a/lib/calendar/test/ta/calendar/core_iter_test.clj b/lib/calendar/test/ta/calendar/core_iter_test.clj new file mode 100644 index 00000000..124d642e --- /dev/null +++ b/lib/calendar/test/ta/calendar/core_iter_test.clj @@ -0,0 +1,183 @@ +(ns ta.calendar.core-iter-test + (:require [clojure.test :refer :all] + [tick.core :as t] + [ta.helper.date :refer [at-time]] + [ta.calendar.data.dates :refer :all] + [quanta.calendar.core :refer [current-close current-open]] + [ta.calendar.calendars :as cal] + [ta.calendar.helper :as h])) + +; CURRENT CLOSE +(defn test-current-close-on-interval-boundary [calendar-kw] + (let [{:keys [open close timezone] :as cal} (calendar-kw cal/calendars) + cal-thursday-open-plus-4h (-> (at-time (t/date "2024-02-08") open timezone) (t/>> (t/new-duration 4 :hours))) + cal-thursday-open-plus-4h-minus-1m (-> cal-thursday-open-plus-4h (t/<< (t/new-duration 1 :minutes))) + cal-thursday-open-plus-4h-minus-15m (-> cal-thursday-open-plus-4h (t/<< (t/new-duration 15 :minutes))) + cal-thursday-open-plus-4h-minus-1h (-> cal-thursday-open-plus-4h (t/<< (t/new-duration 1 :hours))) + cal-thursday-open-plus-4h-minus-4h (-> cal-thursday-open-plus-4h (t/<< (t/new-duration 4 :hours))) + cal-wednesday-close (at-time (t/date "2024-02-07") close timezone)] + (testing "dt on interval boundary" + ; 1 min + (is (t/= cal-thursday-open-plus-4h (current-close [calendar-kw :m] cal-thursday-open-plus-4h))) + (is (not (t/= cal-thursday-open-plus-4h-minus-1m (current-close [calendar-kw :m] cal-thursday-open-plus-4h)))) + ; 15 min + (is (t/= cal-thursday-open-plus-4h (current-close [calendar-kw :m15] cal-thursday-open-plus-4h))) + (is (not (t/= cal-thursday-open-plus-4h-minus-15m (current-close [calendar-kw :m15] cal-thursday-open-plus-4h)))) + ; 1 hour + (is (t/= cal-thursday-open-plus-4h (current-close [calendar-kw :h] cal-thursday-open-plus-4h))) + (is (not (t/= cal-thursday-open-plus-4h-minus-1h (current-close [calendar-kw :h] cal-thursday-open-plus-4h)))) + ; 4 hour + (is (t/= cal-thursday-open-plus-4h (current-close [calendar-kw :h4] cal-thursday-open-plus-4h))) + (is (not (t/= cal-thursday-open-plus-4h-minus-4h (current-close [calendar-kw :h4] cal-thursday-open-plus-4h)))) + ; 1 day + (is (t/= cal-wednesday-close (current-close [calendar-kw :d] cal-thursday-open-plus-4h))) + (is (not (t/= cal-thursday-open-plus-4h (current-close [calendar-kw :d] cal-thursday-open-plus-4h)))) + ))) + +(defn test-current-close-on-trading-open [calendar-kw] + ;; TODO make more generic. not all calendar open time is midnight... + (let [{:keys [open close timezone] :as cal} (calendar-kw cal/calendars) + cal-thursday-open (at-time (t/date "2024-02-08") open timezone) + cal-wednesday-close (at-time (t/date "2024-02-07") close timezone) + cal-thursday-open-plus-1m (-> cal-thursday-open (t/>> (t/new-duration 1 :minutes))) + cal-thursday-open-plus-15m (-> cal-thursday-open (t/>> (t/new-duration 15 :minutes))) + cal-thursday-open-plus-1h (-> cal-thursday-open (t/>> (t/new-duration 1 :hours))) + cal-thursday-open-plus-4h (-> cal-thursday-open (t/>> (t/new-duration 4 :hours)))] + (testing "dt on trading open boundary" + ; 1 min + (is (t/= cal-wednesday-close (current-close [calendar-kw :m] cal-thursday-open))) + (is (not (t/= cal-thursday-open-plus-1m (current-close [calendar-kw :m] cal-thursday-open)))) + ; 15 min + (is (t/= cal-wednesday-close (current-close [calendar-kw :m15] cal-thursday-open))) + (is (not (t/= cal-thursday-open-plus-15m (current-close [calendar-kw :m15] cal-thursday-open)))) + ; 1 hour + (is (t/= cal-wednesday-close (current-close [calendar-kw :h] cal-thursday-open))) + (is (not (t/= cal-thursday-open-plus-1h (current-close [calendar-kw :h] cal-thursday-open)))) + ; 4 hour + (is (t/= cal-wednesday-close (current-close [calendar-kw :h4] cal-thursday-open))) + (is (not (t/= cal-thursday-open-plus-4h (current-close [calendar-kw :h4] cal-thursday-open)))) + ; 1 day + (is (t/= cal-wednesday-close (current-close [calendar-kw :d] cal-thursday-open))) + (is (not (t/= cal-thursday-open-plus-4h (current-close [calendar-kw :d] cal-thursday-open)))) + ))) + +(defn test-current-close-on-trading-close [calendar-kw] + ;; TODO make more generic. not all calendar open time is midnight... + (let [{:keys [close timezone] :as cal} (calendar-kw cal/calendars) + cal-thursday-close (at-time (t/date "2024-02-08") close timezone) + cal-friday-open (at-time (t/date "2024-02-09") close timezone) + cal-friday-open-plus-1m (-> cal-friday-open (t/>> (t/new-duration 1 :minutes))) + cal-friday-open-plus-15m (-> cal-friday-open (t/>> (t/new-duration 15 :minutes))) + cal-friday-open-plus-1h (-> cal-friday-open (t/>> (t/new-duration 1 :hours))) + cal-friday-open-plus-4h (-> cal-friday-open (t/>> (t/new-duration 4 :hours)))] + (testing "dt on trading close boundary" + ; 1 min + (is (t/= cal-thursday-close (current-close [calendar-kw :m] cal-thursday-close))) + (is (not (t/= cal-friday-open-plus-1m (current-close [calendar-kw :m] cal-thursday-close)))) + ; 15 min + (is (t/= cal-thursday-close (current-close [calendar-kw :m15] cal-thursday-close))) + (is (not (t/= cal-friday-open-plus-15m (current-close [calendar-kw :m15] cal-thursday-close)))) + ; 1 hour + (is (t/= cal-thursday-close (current-close [calendar-kw :h] cal-thursday-close))) + (is (not (t/= cal-friday-open-plus-1h (current-close [calendar-kw :h] cal-thursday-close)))) + ; 4 hour + (is (t/= cal-thursday-close (current-close [calendar-kw :h4] cal-thursday-close))) + (is (not (t/= cal-friday-open-plus-4h (current-close [calendar-kw :h4] cal-thursday-close)))) + ; 1 day + (is (t/= cal-thursday-close (current-close [calendar-kw :d] cal-thursday-close))) + (is (not (t/= cal-friday-open-plus-4h (current-close [calendar-kw :d] cal-thursday-close)))) + ))) + + +; CURRENT OPEN +(defn test-current-open-on-interval-boundary [calendar-kw] + (let [{:keys [open timezone] :as cal} (calendar-kw cal/calendars) + cal-thursday-open (at-time (t/date "2024-02-08") open timezone) + cal-thursday-open-plus-4h (-> cal-thursday-open (t/>> (t/new-duration 4 :hours))) + cal-thursday-open-plus-4h-minus-1m (-> cal-thursday-open-plus-4h (t/<< (t/new-duration 1 :minutes))) + cal-thursday-open-plus-4h-minus-15m (-> cal-thursday-open-plus-4h (t/<< (t/new-duration 15 :minutes))) + cal-thursday-open-plus-4h-minus-1h (-> cal-thursday-open-plus-4h (t/<< (t/new-duration 1 :hours))) + cal-thursday-open-plus-4h-minus-4h (-> cal-thursday-open-plus-4h (t/<< (t/new-duration 4 :hours)))] + (testing "dt on interval boundary" + ; 1 min + (is (t/= cal-thursday-open-plus-4h (current-open [calendar-kw :m] cal-thursday-open-plus-4h))) + (is (not (t/= cal-thursday-open-plus-4h-minus-1m (current-open [calendar-kw :m] cal-thursday-open-plus-4h)))) + ; 15 min + (is (t/= cal-thursday-open-plus-4h (current-open [calendar-kw :m15] cal-thursday-open-plus-4h))) + (is (not (t/= cal-thursday-open-plus-4h-minus-15m (current-open [calendar-kw :m15] cal-thursday-open-plus-4h)))) + ; 1 hour + (is (t/= cal-thursday-open-plus-4h (current-open [calendar-kw :h] cal-thursday-open-plus-4h))) + (is (not (t/= cal-thursday-open-plus-4h-minus-1h (current-open [calendar-kw :h] cal-thursday-open-plus-4h)))) + ; 4 hour + (is (t/= cal-thursday-open-plus-4h (current-open [calendar-kw :h4] cal-thursday-open-plus-4h))) + (is (not (t/= cal-thursday-open-plus-4h-minus-4h (current-open [calendar-kw :h4] cal-thursday-open-plus-4h)))) + ; 1 day + (is (t/= cal-thursday-open (current-open [calendar-kw :d] cal-thursday-open-plus-4h))) + (is (not (t/= cal-thursday-open-plus-4h (current-open [calendar-kw :d] cal-thursday-open-plus-4h)))) + ))) + +(defn test-current-open-on-trading-open [calendar-kw] + ;; TODO make more generic. not all calendar open time is midnight... + (let [{:keys [open timezone] :as cal} (calendar-kw cal/calendars) + cal-thursday-open (at-time (t/date "2024-02-08") open timezone) + cal-thursday-open-minus-1m (-> cal-thursday-open (t/<< (t/new-duration 1 :minutes))) + cal-thursday-open-minus-15m (-> cal-thursday-open (t/<< (t/new-duration 15 :minutes))) + cal-thursday-open-minus-1h (-> cal-thursday-open (t/<< (t/new-duration 1 :hours))) + cal-thursday-open-minus-4h (-> cal-thursday-open (t/<< (t/new-duration 4 :hours)))] + (testing "dt on trading open boundary" + ; 1 min + (is (t/= cal-thursday-open (current-open [calendar-kw :m] cal-thursday-open))) + (is (not (t/= cal-thursday-open-minus-1m (current-open [calendar-kw :m] cal-thursday-open)))) + ; 15 min + (is (t/= cal-thursday-open (current-open [calendar-kw :m15] cal-thursday-open))) + (is (not (t/= cal-thursday-open-minus-15m (current-open [calendar-kw :m15] cal-thursday-open)))) + ; 1 hour + (is (t/= cal-thursday-open (current-open [calendar-kw :h] cal-thursday-open))) + (is (not (t/= cal-thursday-open-minus-1h (current-open [calendar-kw :h] cal-thursday-open)))) + ; 4 hour + (is (t/= cal-thursday-open (current-open [calendar-kw :h4] cal-thursday-open))) + (is (not (t/= cal-thursday-open-minus-4h (current-open [calendar-kw :h4] cal-thursday-open)))) + ; 1 day + (is (t/= cal-thursday-open (current-open [calendar-kw :d] cal-thursday-open))) + (is (not (t/= cal-thursday-open-minus-4h (current-open [calendar-kw :d] cal-thursday-open)))) + ))) + +(defn test-current-open-on-trading-close [calendar-kw] + ;; TODO make more generic. not all calendar open time is midnight... + (let [{:keys [close open timezone] :as cal} (calendar-kw cal/calendars) + cal-thursday-open (at-time (t/date "2024-02-08") open timezone) + cal-thursday-close (at-time (t/date "2024-02-08") close timezone) + cal-friday-open (at-time (t/date "2024-02-09") open timezone) + aligned-close (if (h/midnight-close? close) + cal-friday-open + cal-thursday-close) + cal-close-minus-1m (-> aligned-close (t/<< (t/new-duration 1 :minutes))) + cal-close-minus-15m (-> aligned-close (t/<< (t/new-duration 15 :minutes))) + cal-close-minus-1h (-> aligned-close (t/<< (t/new-duration 1 :hours))) + cal-close-minus-4h (-> aligned-close (t/<< (t/new-duration 4 :hours)))] + (testing "dt on trading close boundary" + ; 1 min + (is (t/= cal-close-minus-1m (current-open [calendar-kw :m] cal-thursday-close))) + (is (not (t/= cal-friday-open (current-open [calendar-kw :m] cal-thursday-close)))) + ; 15 min + (is (t/= cal-close-minus-15m (current-open [calendar-kw :m15] cal-thursday-close))) + (is (not (t/= cal-friday-open (current-open [calendar-kw :m15] cal-thursday-close)))) + ; 1 hour + (is (t/= cal-close-minus-1h (current-open [calendar-kw :h] cal-thursday-close))) + (is (not (t/= cal-friday-open (current-open [calendar-kw :h] cal-thursday-close)))) + ; 4 hour + (is (t/= cal-close-minus-4h (current-open [calendar-kw :h4] cal-thursday-close))) + (is (not (t/= cal-friday-open (current-open [calendar-kw :h4] cal-thursday-close)))) + ; 1 day + (is (t/= cal-thursday-open (current-open [calendar-kw :d] cal-thursday-close))) + (is (not (t/= cal-friday-open (current-open [calendar-kw :d] cal-thursday-close)))) + ))) + +(deftest current-close-crypto + (test-current-close-on-interval-boundary :crypto) + (test-current-close-on-trading-open :crypto) + (test-current-close-on-trading-close :crypto) + (test-current-open-on-interval-boundary :crypto) + (test-current-open-on-trading-open :crypto) + (test-current-open-on-trading-close :crypto) + ) \ No newline at end of file diff --git a/lib/calendar/test/ta/calendar/core_test.clj b/lib/calendar/test/ta/calendar/core_test.clj index d9fd38d8..eb1aa5bf 100644 --- a/lib/calendar/test/ta/calendar/core_test.clj +++ b/lib/calendar/test/ta/calendar/core_test.clj @@ -860,4 +860,23 @@ (is (= (nth fixed-window-crypto-m 9) utc-thursday-23-56)) (is (not (= (nth fixed-window-crypto-m 5) utc-thursday-23-59-59-999))))) ) + + (testing "crypto :d | inside trading day - fixed-window-open" + (let [fixed-window-crypto-d (fixed-window-open [:crypto :d] {:start utc-monday-00-00 + :end utc-sunday-23-59-59-999})] + (is (= (count fixed-window-crypto-d) 7)) + (is (= (nth fixed-window-crypto-d 0) utc-sunday-00-00)) + (is (= (nth fixed-window-crypto-d 1) utc-saturday-00-00)) + (is (= (nth fixed-window-crypto-d 2) utc-friday-00-00)) + (is (= (nth fixed-window-crypto-d 3) utc-thursday-00-00)) + (is (= (nth fixed-window-crypto-d 4) utc-wednesday-00-00)) + (is (= (nth fixed-window-crypto-d 5) utc-tuesday-00-00)) + (is (= (nth fixed-window-crypto-d 6) utc-monday-00-00)) + (is (not (= (nth fixed-window-crypto-d 0) utc-sunday-23-59-59-999))) + )) + + (testing "crypto 1 day => 24 hours" + (is (= 24 (-> (fixed-window [:crypto :h] {:start (t/instant "2024-01-01T01:00:00Z") + :end (t/instant "2024-01-01T23:59:59.999999999Z")}) + count)))) )