Last active
September 26, 2019 10:02
-
-
Save joachimdb/6d363843f749bdaf72352bdd214e554b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule ActivationPolicy.RunningStop do | |
alias __MODULE__ | |
alias ActivationPolicy.Util | |
@moduledoc """ | |
Running stop policy | |
Parameters: | |
- activation_price: the price that must be breached before the policy can become active | |
Once breached, the policy starts monitoring the high (or low, depending on the breach direction) | |
- retrace_pct: retrace % from the high/low where the activation policy becomes active | |
- stop_pct: retrace % from the high/low where the activation policy becomes inactive again | |
""" | |
def init(%{activation_price: _, retrace_pct: _, stop_pct: _} = params, %{ | |
avg_price: last_price | |
}) do | |
{:ok, | |
%{ | |
last_price: last_price, | |
high_or_low: nil, | |
status: nil | |
}} | |
end | |
@doc """ | |
iex> params = %{activation_price: 2, retrace_pct: 0.1, stop_pct: 0.2} | |
iex> {:ok, state} = init(params, %{avg_price: 1}) | |
iex> update(params, state, %{avg_price: 0.9}) | |
{:ok, %{last_price: 0.9, high_or_low: nil, status: nil}} | |
iex> update(params, state, %{avg_price: 1.1}).status | |
{:ok, %{last_price: 1.1, high_or_low: nil, status: nil}} | |
iex> update(params, state, %{avg_price: 2.0}).status | |
{:ok, %{last_price: 2.0, high_or_low: 2.0, status: :tracing}} | |
iex> update(params, state, %{avg_price: 2.5}).status | |
{:ok, %{last_price: 2.5, high_or_low: 2.5, status: :tracing}} | |
iex> state = update(params, state, %{avg_price: 10}) | |
{:ok, %{last_price: 10, high_or_low: 10, status: :tracing}} | |
iex> update(params, state, %{avg_price: 11}).status | |
{:ok, %{last_price: 11, high_or_low: 11, status: :tracing}} | |
iex> update(params, state, %{avg_price: 9.5}).status | |
{:ok, %{last_price: 9.5, high_or_low: 10, status: :tracing}} | |
iex> update(params, state, %{avg_price: 9}).status | |
{:ok, %{last_price: 9, high_or_low: 10, status: :active}} | |
iex> update(params, state, %{avg_price: 8.5}).status | |
{:ok, %{last_price: 8.5, high_or_low: 10, status: :active}} | |
iex> update(params, state, %{avg_price: 8}).status | |
{:ok, %{last_price: 8, high_or_low: 10, status: :tracing}} | |
iex> update(params, state, %{avg_price: 7}).status | |
{:ok, %{last_price: 7, high_or_low: 10, status: :tracing}} | |
""" | |
def update(params, state, global_market_state) do | |
current_price = global_market_state.avg_price | |
case state.status do | |
nil -> | |
if not is_nil(state.last_price) and | |
Util.breached?(state.last_price, current_price, params.activation_price) do | |
# activation proce is crossed -> start monitoring high or low | |
{:ok, | |
%{state | last_price: current_price, high_or_low: current_price, status: :tracing}} | |
else | |
{:ok, %{state | last_price: current_price}} | |
end | |
true -> | |
# check if we breached the extremum | |
if Util.breached?(params.activation_price, current_price, state.high_or_low) do | |
{:ok, | |
%{state | last_price: current_price, high_or_low: current_price, status: :tracing}} | |
else | |
# retracing => check retrace percentage | |
retrace_pct = abs(state.high_or_low - current_price) / state.high_or_low | |
if params.retrace_pct <= retrace_pct and params.stop_pct >= retrace_pct do | |
{:ok, %{state | last_price: current_price, status: :active}} | |
else | |
{:ok, %{state | last_price: current_price, status: :tracing}} | |
end | |
end | |
end | |
end | |
def active?(state) do | |
state.status == :active | |
end | |
def probability(params, state, market_state, timespan) do | |
# TODO | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment