Skip to content

Commit

Permalink
exit signal working
Browse files Browse the repository at this point in the history
  • Loading branch information
awb99 committed Jul 14, 2024
1 parent 27cf370 commit 792fe73
Show file tree
Hide file tree
Showing 9 changed files with 102 additions and 57 deletions.
4 changes: 3 additions & 1 deletion lib/trade/src/quanta/quote/random.clj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
(:import [missionary Cancelled]))

(defn initial-price []
(rand 10000))
;(rand 10000)
10000.0
)

(defn update-price [p]
(let [i (rand-int 5)]
Expand Down
32 changes: 2 additions & 30 deletions lib/trade/src/quanta/trade/position.clj
Original file line number Diff line number Diff line change
Expand Up @@ -16,37 +16,9 @@
(order->position order)
(error order)))

(defn ExitSignal
"returns a missionary task.
task will eventually return either of :time :profit :loss"
[algo-opts position]
(let [exit-time (get-exit-time algo-opts (:entry-date position))
exit-tasks (->> [(when exit-time
(time-trigger exit-time))]
(remove nil?))]
(apply m/race exit-tasks)))


(defn ExitPosition [algo-opts position]
;(M/ap (m/?>
)
(comment
(require '[tick.core :as t])
(def algo-opts {:calendar [:crypto :m]
:exit [:time 2]})
(def position {:entry-date (t/instant)})

(m/? (ExitSignal algo-opts position))
;; => :time

;; this one has a position that is older and older, so
;; it might be that this task returns immediately, because
;; the current time is already below the time of the exit-date

(m/? (ExitSignal algo-opts {:entry-date (t/instant)}))
;; => :time




;
)

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
(ns quanta.trade.position.size)
(ns quanta.trade.position.entry.size)


(defmulti positionsize
Expand Down
63 changes: 44 additions & 19 deletions lib/trade/src/quanta/trade/position/exit/price.clj
Original file line number Diff line number Diff line change
@@ -1,29 +1,54 @@
(ns quanta.trade.position.exit.price
(:require
[tick.core :as t]
[missionary.core :as m]
[quanta.trade.position.exit :refer [get-exit-rule]]))
[missionary.core :as m]
[quanta.trade.position.exit.rule :refer [get-exit-rule]]
[quanta.trade.position.working :refer [working-position]]))

(defn trailing-return [position]
(let [working-position (working-position position)]
(m/latest :ret-prct working-position)))

(defn profit-trigger
"returns a missionary task that emits :profit when target is met.
if no profit-percent exit-rule is specified it returns nil
if not task continues running."
[algo-opts position]
(let [[_ target] (get-exit-rule algo-opts :profit-percent)]
(when target
(let [prct (trailing-return position)
rf (fn [_ tp]
(println "trailing profit " (:asset position) ": " tp " target: " target)
(when (> tp target)
(reduced :profit)))]
(m/reduce rf nil prct)))))

(defn loss-trigger
"returns a missionary task that emits :loss when target is met.
if no :loss-percent exit-rule is specified it returns nil.
if not task continues running."
[algo-opts position]
(let [[_ target] (get-exit-rule algo-opts :loss-percent)]
(when target
(let [prct (trailing-return position)
rf (fn [_ tp]
(println "trailing loss " (:asset position) ": " tp " target: " target)
(when (< tp (- 0.0 target))
(reduced :loss)))]
(m/reduce rf nil prct)))))

(comment
(def algo-opts {:asset "BTCUSDT"
:exit [:profit-percent 1.0]})

(defn get-exit-profit [algo-opts position]
(let [{:keys [calendar]} algo-opts
[exchange-kw interval-kw] calendar
bars (get-time-bars algo-opts)]
(when bars
(let [cal-seq (calendar-seq exchange-kw interval-kw entry-date)
window (take bars cal-seq)]
#_{:start (first window)
:end (last window)}
(last window)))))
(def position
{:asset "BTCUSDT"
:qty 500
:entry-price 10000.0})

(m/? (profit-trigger algo-opts position))

;
)

(defn profit-trigger [exit-time]
(let [exit-long (-> exit-time t/instant t/long)
now-long (-> t/instant t/long)
diff-ms (* 1000 (- exit-long now-long))
diff-ms (max diff-ms 1)]
(m/sleep diff-ms :time)))


Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
(ns quanta.trade.position.exit)
(ns quanta.trade.position.exit.rule)

(defn get-exit-rule [algo-opts rule-kw]
(let [{:keys [exit]} algo-opts
Expand Down
46 changes: 46 additions & 0 deletions lib/trade/src/quanta/trade/position/exit/signal.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
(ns quanta.trade.position.exit.signal
(:require
[missionary.core :as m]
[quanta.trade.position.exit.time :refer [get-exit-time time-trigger]]
[quanta.trade.position.exit.price :refer [profit-trigger loss-trigger]]))


(defn exit-signal
"returns a missionary task.
task will eventually return either of :time :profit :loss"
[algo-opts position]
(let [exit-time (get-exit-time algo-opts (:entry-date position))
exit-tasks (->> [(profit-trigger algo-opts position)
(loss-trigger algo-opts position)
(when exit-time
(time-trigger exit-time))]
(remove nil?))]
(apply m/race exit-tasks)))


(comment

(require '[tick.core :as t])
(def algo-opts {:calendar [:crypto :m]
:exit [:loss-percent 2.0
:profit-percent 100.0
:time 2]})
(def position {:asset "BTCUSDT"
:side :long
:entry-date (t/instant)
:entry-price 10000.0
:qty 0.1})


(m/? (exit-signal algo-opts position))
;; => :time or :profit or :loss

;; this one has a position that is older and older, so
;; it might be that this task returns immediately, because
;; the current time is already below the time of the exit-date

(m/? (exit-signal algo-opts {:entry-date (t/instant)}))
;; => :time

;
)
2 changes: 1 addition & 1 deletion lib/trade/src/quanta/trade/position/exit/time.clj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
[tick.core :as t]
[missionary.core :as m]
[ta.calendar.core :refer [calendar-seq]]
[quanta.trade.position.exit :refer [get-exit-rule]]
[quanta.trade.position.exit.rule :refer [get-exit-rule]]
))

(defn get-time-bars [algo-opts]
Expand Down
6 changes: 3 additions & 3 deletions lib/trade/src/quanta/trade/position/working.clj
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
:win? (> abs-ret 0.0))
roundtrip)))

(defn calculate-position [position]
(defn working-position [position]
(m/ap
; startup
(println "start calculating position: " position)
Expand All @@ -33,7 +33,7 @@
(comment
(require '[tick.core :as t])
(m/? (m/reduce println
(calculate-position {:asset "BTCUSDT"
(working-position {:asset "BTCUSDT"
:qty 500
:entry-price 1000.0
:entry-date (t/instant)})))
Expand Down Expand Up @@ -67,7 +67,7 @@
:ret-prct
:win?] positions))

(let [flows (map calculate-position positions)]
(let [flows (map working-position positions)]
(m/?
(m/reduce (constantly nil)
(apply m/latest print-positions flows))))
Expand Down
2 changes: 1 addition & 1 deletion lib/trade/src/ta/trade/backtest/entry.clj
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
(ns ta.trade.backtest.entry
(:require
[quanta.trade.position.size :refer [positionsize]]
[quanta.trade.position.entry.size :refer [positionsize]]
)
)

Expand Down

0 comments on commit 792fe73

Please sign in to comment.