Deployed 7e7e475 to develop in en with MkDocs 1.6.1 and mike 2.1.4

This commit is contained in:
github-actions[bot]
2026-03-31 05:20:03 +00:00
parent df495f4472
commit 970aa93176
44 changed files with 13314 additions and 6959 deletions
+410 -129
View File
@@ -2142,6 +2142,139 @@
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#update-binance-cached-leverage-tiers" class="md-nav__link">
<span class="md-ellipsis">
Update binance cached leverage tiers
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#updating-example-notebooks" class="md-nav__link">
<span class="md-ellipsis">
Updating example notebooks
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#backtest-documentation-results" class="md-nav__link">
<span class="md-ellipsis">
Backtest documentation results
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#continuous-integration" class="md-nav__link">
<span class="md-ellipsis">
Continuous integration
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#creating-a-release" class="md-nav__link">
<span class="md-ellipsis">
Creating a release
</span>
</a>
<nav class="md-nav" aria-label="Creating a release">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#create-release-branch" class="md-nav__link">
<span class="md-ellipsis">
Create release branch
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#create-changelog-from-git-commits" class="md-nav__link">
<span class="md-ellipsis">
Create changelog from git commits
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#frequi-release" class="md-nav__link">
<span class="md-ellipsis">
FreqUI release
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#create-github-release-tag" class="md-nav__link">
<span class="md-ellipsis">
Create github release / tag
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#releases" class="md-nav__link">
<span class="md-ellipsis">
Releases
</span>
</a>
<nav class="md-nav" aria-label="Releases">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#pypi" class="md-nav__link">
<span class="md-ellipsis">
pypi
</span>
</a>
</li>
</ul>
@@ -2535,6 +2668,139 @@
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#update-binance-cached-leverage-tiers" class="md-nav__link">
<span class="md-ellipsis">
Update binance cached leverage tiers
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#updating-example-notebooks" class="md-nav__link">
<span class="md-ellipsis">
Updating example notebooks
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#backtest-documentation-results" class="md-nav__link">
<span class="md-ellipsis">
Backtest documentation results
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#continuous-integration" class="md-nav__link">
<span class="md-ellipsis">
Continuous integration
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#creating-a-release" class="md-nav__link">
<span class="md-ellipsis">
Creating a release
</span>
</a>
<nav class="md-nav" aria-label="Creating a release">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#create-release-branch" class="md-nav__link">
<span class="md-ellipsis">
Create release branch
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#create-changelog-from-git-commits" class="md-nav__link">
<span class="md-ellipsis">
Create changelog from git commits
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#frequi-release" class="md-nav__link">
<span class="md-ellipsis">
FreqUI release
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#create-github-release-tag" class="md-nav__link">
<span class="md-ellipsis">
Create github release / tag
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#releases" class="md-nav__link">
<span class="md-ellipsis">
Releases
</span>
</a>
<nav class="md-nav" aria-label="Releases">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#pypi" class="md-nav__link">
<span class="md-ellipsis">
pypi
</span>
</a>
</li>
</ul>
@@ -2574,17 +2840,17 @@
<p>Documentation is available at <a href="https://www.freqtrade.io/">https://freqtrade.io</a> and needs to be provided with every new feature PR.</p>
<p>Special fields for the documentation (like Note boxes, ...) can be found <a href="https://squidfunk.github.io/mkdocs-material/reference/admonitions/">here</a>.</p>
<p>To test the documentation locally use the following commands.</p>
<p><code>bash
pip install -r docs/requirements-docs.txt
mkdocs serve</code></p>
<div class="highlight"><pre><span></span><code>pip<span class="w"> </span>install<span class="w"> </span>-r<span class="w"> </span>docs/requirements-docs.txt
mkdocs<span class="w"> </span>serve
</code></pre></div>
<p>This will spin up a local server (usually on port 8000) so you can see if everything looks as you'd like it to.</p>
<h2 id="developer-setup">Developer setup<a class="headerlink" href="#developer-setup" title="Permanent link">&para;</a></h2>
<p>To configure a development environment, you can either use the provided <a href="#devcontainer-setup">DevContainer</a>, or use the <code>setup.sh</code> script and answer "y" when asked "Do you want to install dependencies for dev [y/N]? ".
Alternatively (e.g. if your system is not supported by the setup.sh script), follow the manual installation process and run <code>pip3 install -r requirements-dev.txt</code> - followed by <code>pip3 install -e .[all]</code>.</p>
<p>This will install all required tools for development, including <code>pytest</code>, <code>ruff</code>, <code>mypy</code>, and <code>coveralls</code>.</p>
<p>Run the following command to install the git hook scripts:</p>
<p><code>bash
pre-commit install</code></p>
<div class="highlight"><pre><span></span><code>pre-commit<span class="w"> </span>install
</code></pre></div>
<p>These pre-commit scripts check your changes automatically before each commit.<br />
If any formatting issues are found, the commit will fail and will prompt for fixes.
This reduces unnecessary CI failures, reduces maintenance burden, and improves code quality.</p>
@@ -2613,34 +2879,33 @@ If necessary, the Freqtrade team can assist and give guidance with writing good
<p>Freqtrade uses 2 main methods to check log content in tests, <code>log_has()</code> and <code>log_has_re()</code> (to check using regex, in case of dynamic log-messages).
These are available from <code>conftest.py</code> and can be imported in any test module.</p>
<p>A sample check looks as follows:</p>
<p>``` python
from tests.conftest import log_has, log_has_re</p>
<p>def test_method_to_test(caplog):
method_to_test()</p>
<div class="codehilite"><pre><span></span><code>assert log_has(&quot;This event happened&quot;, caplog)
# Check regex with trailing number ...
assert log_has_re(r&quot;This dynamic event happened and produced \d+&quot;, caplog)
</code></pre></div>
<div class="highlight"><pre><span></span><code><span class="kn">from</span><span class="w"> </span><span class="nn">tests.conftest</span><span class="w"> </span><span class="kn">import</span> <span class="n">log_has</span><span class="p">,</span> <span class="n">log_has_re</span>
<p>```</p>
<span class="k">def</span><span class="w"> </span><span class="nf">test_method_to_test</span><span class="p">(</span><span class="n">caplog</span><span class="p">):</span>
<span class="n">method_to_test</span><span class="p">()</span>
<span class="k">assert</span> <span class="n">log_has</span><span class="p">(</span><span class="s2">&quot;This event happened&quot;</span><span class="p">,</span> <span class="n">caplog</span><span class="p">)</span>
<span class="c1"># Check regex with trailing number ...</span>
<span class="k">assert</span> <span class="n">log_has_re</span><span class="p">(</span><span class="sa">r</span><span class="s2">&quot;This dynamic event happened and produced \d+&quot;</span><span class="p">,</span> <span class="n">caplog</span><span class="p">)</span>
</code></pre></div>
<h3 id="debug-configuration">Debug configuration<a class="headerlink" href="#debug-configuration" title="Permanent link">&para;</a></h3>
<p>To debug freqtrade, we recommend VSCode (with the Python extension) with the following launch configuration (located in <code>.vscode/launch.json</code>).
Details will obviously vary between setups - but this should work to get you started.</p>
<p><code>json
{
"name": "freqtrade trade",
"type": "debugpy",
"request": "launch",
"module": "freqtrade",
"console": "integratedTerminal",
"args": [
"trade",
// Optional:
// "--userdir", "user_data",
"--strategy",
"MyAwesomeStrategy",
]
},</code></p>
<div class="highlight"><pre><span></span><code><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;name&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;freqtrade trade&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;type&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;debugpy&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;request&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;launch&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;module&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;freqtrade&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;console&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;integratedTerminal&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;args&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span>
<span class="w"> </span><span class="s2">&quot;trade&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="c1">// Optional:</span>
<span class="w"> </span><span class="c1">// &quot;--userdir&quot;, &quot;user_data&quot;,</span>
<span class="w"> </span><span class="s2">&quot;--strategy&quot;</span><span class="p">,</span><span class="w"> </span>
<span class="w"> </span><span class="s2">&quot;MyAwesomeStrategy&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="p">]</span>
<span class="p">},</span>
</code></pre></div>
<p>Command line arguments can be added in the <code>"args"</code> array.
This method can also be used to debug a strategy, by setting the breakpoints within the strategy.</p>
<p>A similar setup can also be taken for Pycharm - using <code>freqtrade</code> as module name, and setting the command line arguments as "parameters".</p>
@@ -2662,7 +2927,7 @@ If your environment has not been detected, you can also pick a path manually.</p
<p>Freqtrade Exceptions all inherit from <code>FreqtradeException</code>.
This general class of error should however not be used directly. Instead, multiple specialized sub-Exceptions exist.</p>
<p>Below is an outline of exception inheritance hierarchy:</p>
<p><code>+ FreqtradeException
<div class="highlight"><pre><span></span><code>+ FreqtradeException
|
+---+ OperationalException
| |
@@ -2684,7 +2949,8 @@ This general class of error should however not be used directly. Instead, multip
| |
| +---+ InsufficientFundsError
|
+---+ StrategyError</code></p>
+---+ StrategyError
</code></pre></div>
<hr />
<h2 id="plugins">Plugins<a class="headerlink" href="#plugins" title="Permanent link">&para;</a></h2>
<h3 id="pairlists">Pairlists<a class="headerlink" href="#pairlists" title="Permanent link">&para;</a></h3>
@@ -2695,12 +2961,12 @@ Hopefully you also want to contribute this back upstream.</p>
<p>This is a simple Handler, which however serves as a good example on how to start developing.</p>
<p>Next, modify the class-name of the Handler (ideally align this with the module filename).</p>
<p>The base-class provides an instance of the exchange (<code>self._exchange</code>) the pairlist manager (<code>self._pairlistmanager</code>), as well as the main configuration (<code>self._config</code>), the pairlist dedicated configuration (<code>self._pairlistconfig</code>) and the absolute position within the list of pairlists.</p>
<p><code>python
self._exchange = exchange
self._pairlistmanager = pairlistmanager
self._config = config
self._pairlistconfig = pairlistconfig
self._pairlist_pos = pairlist_pos</code></p>
<div class="highlight"><pre><span></span><code> <span class="bp">self</span><span class="o">.</span><span class="n">_exchange</span> <span class="o">=</span> <span class="n">exchange</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_pairlistmanager</span> <span class="o">=</span> <span class="n">pairlistmanager</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_config</span> <span class="o">=</span> <span class="n">config</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_pairlistconfig</span> <span class="o">=</span> <span class="n">pairlistconfig</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_pairlist_pos</span> <span class="o">=</span> <span class="n">pairlist_pos</span>
</code></pre></div>
<div class="admonition tip">
<p class="admonition-title">Tip</p>
<p>Don't forget to register your pairlist in <code>constants.py</code> under the variable <code>AVAILABLE_PAIRLISTS</code> - otherwise it will not be selectable.</p>
@@ -2727,11 +2993,11 @@ Hopefully you also want to contribute this back upstream.</p>
<p>Validations are optional, the parent class exposes a <code>verify_blacklist(pairlist)</code> and <code>_whitelist_for_active_markets(pairlist)</code> to do default filters. Use this if you limit your result to a certain number of pairs - so the end result is not shorter than expected.</p>
<p>In <code>VolumePairList</code>, this implements different methods of sorting, does early validation so only the expected number of pairs is returned.</p>
<h5 id="sample">sample<a class="headerlink" href="#sample" title="Permanent link">&para;</a></h5>
<p><code>python
def filter_pairlist(self, pairlist: list[str], tickers: dict) -&gt; List[str]:
# Generate dynamic whitelist
pairs = self._calculate_pairlist(pairlist, tickers)
return pairs</code></p>
<div class="highlight"><pre><span></span><code> <span class="k">def</span><span class="w"> </span><span class="nf">filter_pairlist</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">pairlist</span><span class="p">:</span> <span class="nb">list</span><span class="p">[</span><span class="nb">str</span><span class="p">],</span> <span class="n">tickers</span><span class="p">:</span> <span class="nb">dict</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]:</span>
<span class="c1"># Generate dynamic whitelist</span>
<span class="n">pairs</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_calculate_pairlist</span><span class="p">(</span><span class="n">pairlist</span><span class="p">,</span> <span class="n">tickers</span><span class="p">)</span>
<span class="k">return</span> <span class="n">pairs</span>
</code></pre></div>
<h3 id="protections">Protections<a class="headerlink" href="#protections" title="Permanent link">&para;</a></h3>
<p>Best read the <a href="../plugins/#protections">Protection documentation</a> to understand protections.
This Guide is directed towards Developers who want to develop a new protection.</p>
@@ -2824,59 +3090,63 @@ The below are "extras", which will make an exchange better (feature-complete) -
To demonstrate this, we'll use daily candles (<code>"1d"</code>) to keep things simple.
We query the api (<code>ct.fetch_ohlcv()</code>) for the timeframe and look at the date of the last entry. If this entry changes or shows the date of a "incomplete" candle, then we should drop this since having incomplete candles is problematic because indicators assume that only complete candles are passed to them, and will generate a lot of false buy signals. By default, we're therefore removing the last candle assuming it's incomplete.</p>
<p>To check how the new exchange behaves, you can use the following snippet:</p>
<p>``` python
import ccxt
from datetime import datetime, timezone
from freqtrade.data.converter import ohlcv_to_dataframe
ct = ccxt.binance() # Use the exchange you're testing
timeframe = "1d"
pair = "BTC/USDT" # Make sure to use a pair that exists on that exchange!
raw = ct.fetch_ohlcv(pair, timeframe=timeframe)</p>
<h1 id="convert-to-dataframe">convert to dataframe<a class="headerlink" href="#convert-to-dataframe" title="Permanent link">&para;</a></h1>
<p>df1 = ohlcv_to_dataframe(raw, timeframe, pair=pair, drop_incomplete=False)</p>
<p>print(df1.tail(1))
print(datetime.now(timezone.utc))
```</p>
<p><code>output
date open high low close volume
499 2019-06-08 00:00:00+00:00 0.000007 0.000007 0.000007 0.000007 26264344.0
2019-06-09 12:30:27.873327</code></p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span><span class="w"> </span><span class="nn">ccxt</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">datetime</span><span class="w"> </span><span class="kn">import</span> <span class="n">datetime</span><span class="p">,</span> <span class="n">timezone</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">freqtrade.data.converter</span><span class="w"> </span><span class="kn">import</span> <span class="n">ohlcv_to_dataframe</span>
<span class="n">ct</span> <span class="o">=</span> <span class="n">ccxt</span><span class="o">.</span><span class="n">binance</span><span class="p">()</span> <span class="c1"># Use the exchange you&#39;re testing</span>
<span class="n">timeframe</span> <span class="o">=</span> <span class="s2">&quot;1d&quot;</span>
<span class="n">pair</span> <span class="o">=</span> <span class="s2">&quot;BTC/USDT&quot;</span> <span class="c1"># Make sure to use a pair that exists on that exchange!</span>
<span class="n">raw</span> <span class="o">=</span> <span class="n">ct</span><span class="o">.</span><span class="n">fetch_ohlcv</span><span class="p">(</span><span class="n">pair</span><span class="p">,</span> <span class="n">timeframe</span><span class="o">=</span><span class="n">timeframe</span><span class="p">)</span>
<span class="c1"># convert to dataframe</span>
<span class="n">df1</span> <span class="o">=</span> <span class="n">ohlcv_to_dataframe</span><span class="p">(</span><span class="n">raw</span><span class="p">,</span> <span class="n">timeframe</span><span class="p">,</span> <span class="n">pair</span><span class="o">=</span><span class="n">pair</span><span class="p">,</span> <span class="n">drop_incomplete</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="n">df1</span><span class="o">.</span><span class="n">tail</span><span class="p">(</span><span class="mi">1</span><span class="p">))</span>
<span class="nb">print</span><span class="p">(</span><span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">(</span><span class="n">timezone</span><span class="o">.</span><span class="n">utc</span><span class="p">))</span>
</code></pre></div>
<div class="highlight"><pre><span></span><code><span class="go"> date open high low close volume </span>
<span class="go">499 2019-06-08 00:00:00+00:00 0.000007 0.000007 0.000007 0.000007 26264344.0 </span>
<span class="go">2019-06-09 12:30:27.873327</span>
</code></pre></div>
<p>The output will show the last entry from the Exchange as well as the current UTC date.
If the day shows the same day, then the last candle can be assumed as incomplete and should be dropped (leave the setting <code>"ohlcv_partial_candle"</code> from the exchange-class untouched / True). Otherwise, set <code>"ohlcv_partial_candle"</code> to <code>False</code> to not drop Candles (shown in the example above).
Another way is to run this command multiple times in a row and observe if the volume is changing (while the date remains the same).</p>
<h3 id="update-binance-cached-leverage-tiers">Update binance cached leverage tiers<a class="headerlink" href="#update-binance-cached-leverage-tiers" title="Permanent link">&para;</a></h3>
<p>Updating leveraged tiers should be done regularly - and requires an authenticated account with futures enabled.</p>
<p>``` python
import ccxt
import json
from pathlib import Path</p>
<p>exchange = ccxt.binance({
'apiKey': '<apikey>',
'secret': '<secret>',
'options': {'defaultType': 'swap'}
})
_ = exchange.load_markets()</p>
<p>lev_tiers = exchange.fetch_leverage_tiers()</p>
<h1 id="assumes-this-is-running-in-the-root-of-the-repository">Assumes this is running in the root of the repository.<a class="headerlink" href="#assumes-this-is-running-in-the-root-of-the-repository" title="Permanent link">&para;</a></h1>
<p>file = Path('freqtrade/exchange/binance_leverage_tiers.json')
json.dump(dict(sorted(lev_tiers.items())), file.open('w'), indent=2)</p>
<p>```</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span><span class="w"> </span><span class="nn">ccxt</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">json</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">pathlib</span><span class="w"> </span><span class="kn">import</span> <span class="n">Path</span>
<span class="n">exchange</span> <span class="o">=</span> <span class="n">ccxt</span><span class="o">.</span><span class="n">binance</span><span class="p">({</span>
<span class="s1">&#39;apiKey&#39;</span><span class="p">:</span> <span class="s1">&#39;&lt;apikey&gt;&#39;</span><span class="p">,</span>
<span class="s1">&#39;secret&#39;</span><span class="p">:</span> <span class="s1">&#39;&lt;secret&gt;&#39;</span><span class="p">,</span>
<span class="s1">&#39;options&#39;</span><span class="p">:</span> <span class="p">{</span><span class="s1">&#39;defaultType&#39;</span><span class="p">:</span> <span class="s1">&#39;swap&#39;</span><span class="p">}</span>
<span class="p">})</span>
<span class="n">_</span> <span class="o">=</span> <span class="n">exchange</span><span class="o">.</span><span class="n">load_markets</span><span class="p">()</span>
<span class="n">lev_tiers</span> <span class="o">=</span> <span class="n">exchange</span><span class="o">.</span><span class="n">fetch_leverage_tiers</span><span class="p">()</span>
<span class="c1"># Assumes this is running in the root of the repository.</span>
<span class="n">file</span> <span class="o">=</span> <span class="n">Path</span><span class="p">(</span><span class="s1">&#39;freqtrade/exchange/binance_leverage_tiers.json&#39;</span><span class="p">)</span>
<span class="n">json</span><span class="o">.</span><span class="n">dump</span><span class="p">(</span><span class="nb">dict</span><span class="p">(</span><span class="nb">sorted</span><span class="p">(</span><span class="n">lev_tiers</span><span class="o">.</span><span class="n">items</span><span class="p">())),</span> <span class="n">file</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="s1">&#39;w&#39;</span><span class="p">),</span> <span class="n">indent</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>
</code></pre></div>
<p>This file should then be contributed upstream, so others can benefit from this, too.</p>
<h2 id="updating-example-notebooks">Updating example notebooks<a class="headerlink" href="#updating-example-notebooks" title="Permanent link">&para;</a></h2>
<p>To keep the jupyter notebooks aligned with the documentation, the following should be ran after updating a example notebook.</p>
<p><code>bash
jupyter nbconvert --ClearOutputPreprocessor.enabled=True --inplace freqtrade/templates/strategy_analysis_example.ipynb
jupyter nbconvert --ClearOutputPreprocessor.enabled=True --to markdown freqtrade/templates/strategy_analysis_example.ipynb --stdout &gt; docs/strategy_analysis_example.md</code></p>
<div class="highlight"><pre><span></span><code>jupyter<span class="w"> </span>nbconvert<span class="w"> </span>--ClearOutputPreprocessor.enabled<span class="o">=</span>True<span class="w"> </span>--inplace<span class="w"> </span>freqtrade/templates/strategy_analysis_example.ipynb
jupyter<span class="w"> </span>nbconvert<span class="w"> </span>--ClearOutputPreprocessor.enabled<span class="o">=</span>True<span class="w"> </span>--to<span class="w"> </span>markdown<span class="w"> </span>freqtrade/templates/strategy_analysis_example.ipynb<span class="w"> </span>--stdout<span class="w"> </span>&gt;<span class="w"> </span>docs/strategy_analysis_example.md
</code></pre></div>
<h2 id="backtest-documentation-results">Backtest documentation results<a class="headerlink" href="#backtest-documentation-results" title="Permanent link">&para;</a></h2>
<p>To generate backtest outputs, please use the following commands:</p>
<p>``` bash</p>
<h1 id="assume-a-dedicated-user-directory-for-this-output">Assume a dedicated user directory for this output<a class="headerlink" href="#assume-a-dedicated-user-directory-for-this-output" title="Permanent link">&para;</a></h1>
<p>freqtrade create-userdir --userdir user_data_bttest/</p>
<h1 id="set-can_short-true">set can_short = True<a class="headerlink" href="#set-can_short-true" title="Permanent link">&para;</a></h1>
<p>sed -i "s/can_short: bool = False/can_short: bool = True/" user_data_bttest/strategies/sample_strategy.py</p>
<p>freqtrade download-data --timerange 20250625-20250801 --config tests/testdata/config.tests.usdt.json --userdir user_data_bttest/ -t 5m</p>
<p>freqtrade backtesting --config tests/testdata/config.tests.usdt.json -s SampleStrategy --userdir user_data_bttest/ --cache none --timerange 20250701-20250801
```</p>
<div class="highlight"><pre><span></span><code><span class="c1"># Assume a dedicated user directory for this output</span>
freqtrade<span class="w"> </span>create-userdir<span class="w"> </span>--userdir<span class="w"> </span>user_data_bttest/
<span class="c1"># set can_short = True</span>
sed<span class="w"> </span>-i<span class="w"> </span><span class="s2">&quot;s/can_short: bool = False/can_short: bool = True/&quot;</span><span class="w"> </span>user_data_bttest/strategies/sample_strategy.py
freqtrade<span class="w"> </span>download-data<span class="w"> </span>--timerange<span class="w"> </span><span class="m">20250625</span>-20250801<span class="w"> </span>--config<span class="w"> </span>tests/testdata/config.tests.usdt.json<span class="w"> </span>--userdir<span class="w"> </span>user_data_bttest/<span class="w"> </span>-t<span class="w"> </span>5m
freqtrade<span class="w"> </span>backtesting<span class="w"> </span>--config<span class="w"> </span>tests/testdata/config.tests.usdt.json<span class="w"> </span>-s<span class="w"> </span>SampleStrategy<span class="w"> </span>--userdir<span class="w"> </span>user_data_bttest/<span class="w"> </span>--cache<span class="w"> </span>none<span class="w"> </span>--timerange<span class="w"> </span><span class="m">20250701</span>-20250801
</code></pre></div>
<h2 id="continuous-integration">Continuous integration<a class="headerlink" href="#continuous-integration" title="Permanent link">&para;</a></h2>
<p>This documents some decisions taken for the CI Pipeline.</p>
<ul>
@@ -2896,10 +3166,9 @@ jupyter nbconvert --ClearOutputPreprocessor.enabled=True --to markdown freqtrade
<p>Make sure that the <code>stable</code> branch is up-to-date!</p>
</div>
<p>First, pick a commit that's about one week old (to not include latest additions to releases).</p>
<p>``` bash</p>
<h1 id="create-new-branch">create new branch<a class="headerlink" href="#create-new-branch" title="Permanent link">&para;</a></h1>
<p>git checkout -b new_release <commitid>
```</p>
<div class="highlight"><pre><span></span><code><span class="c1"># create new branch</span>
git<span class="w"> </span>checkout<span class="w"> </span>-b<span class="w"> </span>new_release<span class="w"> </span>&lt;commitid&gt;
</code></pre></div>
<p>Determine if crucial bugfixes have been made between this commit and the current state, and eventually cherry-pick these.</p>
<ul>
<li>Merge the release branch (stable) into this branch.</li>
@@ -2909,19 +3178,17 @@ jupyter nbconvert --ClearOutputPreprocessor.enabled=True --to markdown freqtrade
<li>Update develop version to next version following the pattern <code>2025.8-dev</code>.</li>
</ul>
<h3 id="create-changelog-from-git-commits">Create changelog from git commits<a class="headerlink" href="#create-changelog-from-git-commits" title="Permanent link">&para;</a></h3>
<p>``` bash</p>
<h1 id="needs-to-be-done-before-merging-pulling-that-branch">Needs to be done before merging / pulling that branch.<a class="headerlink" href="#needs-to-be-done-before-merging-pulling-that-branch" title="Permanent link">&para;</a></h1>
<p>git log --oneline --no-decorate --no-merges stable..new_release
```</p>
<div class="highlight"><pre><span></span><code><span class="c1"># Needs to be done before merging / pulling that branch.</span>
git<span class="w"> </span>log<span class="w"> </span>--oneline<span class="w"> </span>--no-decorate<span class="w"> </span>--no-merges<span class="w"> </span>stable..new_release
</code></pre></div>
<p>To keep the release-log short, best wrap the full git changelog into a collapsible details section.</p>
<p>```markdown</p>
<details>
<summary>Expand full changelog</summary>
<div class="highlight"><pre><span></span><code>&lt;details&gt;
&lt;summary&gt;Expand full changelog&lt;/summary&gt;
... Full git changelog
</details>
<p>```</p>
&lt;/details&gt;
</code></pre></div>
<h3 id="frequi-release">FreqUI release<a class="headerlink" href="#frequi-release" title="Permanent link">&para;</a></h3>
<p>If FreqUI has been updated substantially, make sure to create a release before merging the release branch.
Make sure that freqUI CI on the release is finished and passed before merging the release.</p>
@@ -2936,31 +3203,44 @@ Make sure that freqUI CI on the release is finished and passed before merging th
</ul>
<details class="tip">
<summary>Release template</summary>
<p>````</p>
<h1 id="highlighted-changes">Highlighted changes<a class="headerlink" href="#highlighted-changes" title="Permanent link">&para;</a></h1>
<ul>
<li>...</li>
</ul>
<h2 id="how-to-update">How to update<a class="headerlink" href="#how-to-update" title="Permanent link">&para;</a></h2>
<p>As always, you can update your bot using one of the following commands:</p>
<h3 id="docker-compose">docker-compose<a class="headerlink" href="#docker-compose" title="Permanent link">&para;</a></h3>
<p><code>bash
<div class="highlight"><pre><span></span><code># Highlighted changes
- ...
## How to update
As always, you can update your bot using one of the following commands:
### docker-compose
```bash
docker-compose pull
docker-compose up -d</code></p>
<h3 id="installation-via-setup-script">Installation via setup script<a class="headerlink" href="#installation-via-setup-script" title="Permanent link">&para;</a></h3>
<p>``` bash</p>
<h1 id="deactivate-venv-and-run">Deactivate venv and run<a class="headerlink" href="#deactivate-venv-and-run" title="Permanent link">&para;</a></h1>
<p>./setup.sh --update
```</p>
<h3 id="plain-native-installation">Plain native installation<a class="headerlink" href="#plain-native-installation" title="Permanent link">&para;</a></h3>
<p><code>bash
docker-compose up -d
```
### Installation via setup script
``` bash
# Deactivate venv and run
./setup.sh --update
```
### Plain native installation
``` bash
git pull
pip install -U -r requirements.txt</code></p>
<p><details>
<summary>Expand full changelog</summary></p>
<p><code>&lt;Paste your changelog here&gt;</code></p>
</details>
<p>````</p>
pip install -U -r requirements.txt
```
&lt;details&gt;
&lt;summary&gt;Expand full changelog&lt;/summary&gt;
```
&lt;Paste your changelog here&gt;
```
&lt;/details&gt;
</code></pre></div>
</details>
<h2 id="releases">Releases<a class="headerlink" href="#releases" title="Permanent link">&para;</a></h2>
<h3 id="pypi">pypi<a class="headerlink" href="#pypi" title="Permanent link">&para;</a></h3>
@@ -2973,14 +3253,15 @@ Manual pypi pushes should not be necessary.</p>
<summary>Manual release</summary>
<p>To manually create a pypi release, please run the following commands:</p>
<p>Additional requirement: <code>wheel</code>, <code>twine</code> (for uploading), account on pypi with proper permissions.</p>
<p>``` bash
pip install -U build
python -m build --sdist --wheel</p>
<h1 id="for-pypi-test-to-check-if-some-change-to-the-installation-did-work">For pypi test (to check if some change to the installation did work)<a class="headerlink" href="#for-pypi-test-to-check-if-some-change-to-the-installation-did-work" title="Permanent link">&para;</a></h1>
<p>twine upload --repository-url <a href="https://test.pypi.org/legacy/">https://test.pypi.org/legacy/</a> dist/*</p>
<h1 id="for-production">For production:<a class="headerlink" href="#for-production" title="Permanent link">&para;</a></h1>
<p>twine upload dist/*
```</p>
<div class="highlight"><pre><span></span><code>pip<span class="w"> </span>install<span class="w"> </span>-U<span class="w"> </span>build
python<span class="w"> </span>-m<span class="w"> </span>build<span class="w"> </span>--sdist<span class="w"> </span>--wheel
<span class="c1"># For pypi test (to check if some change to the installation did work)</span>
twine<span class="w"> </span>upload<span class="w"> </span>--repository-url<span class="w"> </span>https://test.pypi.org/legacy/<span class="w"> </span>dist/*
<span class="c1"># For production:</span>
twine<span class="w"> </span>upload<span class="w"> </span>dist/*
</code></pre></div>
<p>Please don't push non-releases to the productive / real pypi instance.</p>
</details>