Skip to content

Instantly share code, notes, and snippets.

@joachimdb
Last active September 26, 2019 10:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joachimdb/6d363843f749bdaf72352bdd214e554b to your computer and use it in GitHub Desktop.
Save joachimdb/6d363843f749bdaf72352bdd214e554b to your computer and use it in GitHub Desktop.
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