Repository: freqtrade/freqtrade

Issue:
'nan' result in Edge Module
Hi developers, i would like to bring to your attention a computation problem of the edge module that is solved in this way to avoid 0/0 with result 'nan' on the best and worst paris.

I hope you solve it in a more elegant way than mine.
Thank you

https://github.com/freqtrade/freqtrade/blob/1628a0a4f08de4b40617db50fba6d54fe723898b/freqtrade/edge/edge_positioning.py#L313
![Immagine 2020-10-06 215021](https://user-images.githubusercontent.com/72468858/95252943-f99fb800-081d-11eb-9bde-0c02a3f56569.png)



Discussion:
Can you please elaborate what the actual problem is you're trying to solve?

I don't see why having nan should be a problem in the first place - yes, it'll show nan if there are no trades - but when there are no trades, then nan is a valid outcome i think...



Hi xmatthias, the problem is in the case where have no loss trade and all trade are winnning trade: the 'nan' values migrate in the winrate, filtering out the pairs with winrate 100%. 
are you able to share an example output of this?

the impact of this is not clear to me.
Hi Xmatthias
In the attachments you find the same edge results with or without the modify

You can see in the standard version pairs with winrate 1.00 (100%) and expectancy 'nan' that are filtered out.

In the modified version the pair with winrate 100% has expectancy 'inf' and are not filtered out.

I'm not a experienced programmer, i think my metod is really rought, but that work for me.
Thank you

[backtesting-mod.txt](https://github.com/freqtrade/freqtrade/files/5340309/backtesting-mod.txt)
[backtesting.txt](https://github.com/freqtrade/freqtrade/files/5340310/backtesting.txt)

I guess a proper fix should be the following (the problem is a simple 0 division ...)

Would be great if you could give this a try before we incorporate it - i've not been able to get any strategy suitable for edge to do only winning trades for one pair.


```
        df['average_win'] = np.where(df['nb_win_trades'] == 0, 0.0, df['profit_sum'] / df['nb_win_trades'])
        df['average_loss'] = np.where(df['nb_loss_trades'] == 0, 0.0, df['loss_sum'] / df['nb_loss_trades'])
```
Hi xmatthias
i think that it's works fine!
You can see in the attachment

Thank you for all.
Mike 5



![2020-10-08_20-53](https://user-images.githubusercontent.com/72468858/95501259-4ca57680-09a8-11eb-9950-2a481f0276d1.png)


[backtesting.txt](https://github.com/freqtrade/freqtrade/files/5350742/backtesting.txt)


Resolving patch:
diff --git a/freqtrade/edge/edge_positioning.py b/freqtrade/edge/edge_positioning.py
--- a/freqtrade/edge/edge_positioning.py
+++ b/freqtrade/edge/edge_positioning.py
@@ -310,8 +310,10 @@ def _process_expectancy(self, results: DataFrame) -> Dict[str, Any]:
 
         # Calculating number of losing trades, average win and average loss
         df['nb_loss_trades'] = df['nb_trades'] - df['nb_win_trades']
-        df['average_win'] = df['profit_sum'] / df['nb_win_trades']
-        df['average_loss'] = df['loss_sum'] / df['nb_loss_trades']
+        df['average_win'] = np.where(df['nb_win_trades'] == 0, 0.0,
+                                     df['profit_sum'] / df['nb_win_trades'])
+        df['average_loss'] = np.where(df['nb_loss_trades'] == 0, 0.0,
+                                      df['loss_sum'] / df['nb_loss_trades'])
 
         # Win rate = number of profitable trades / number of trades
         df['winrate'] = df['nb_win_trades'] / df['nb_trades']


Test patch:
diff --git a/tests/edge/test_edge.py b/tests/edge/test_edge.py
--- a/tests/edge/test_edge.py
+++ b/tests/edge/test_edge.py
@@ -499,3 +499,61 @@ def test_process_expectancy_remove_pumps(mocker, edge_conf, fee,):
     assert final['TEST/BTC'].stoploss == -0.9
     assert final['TEST/BTC'].nb_trades == len(trades_df) - 1
     assert round(final['TEST/BTC'].winrate, 10) == 0.0
+
+
+def test_process_expectancy_only_wins(mocker, edge_conf, fee,):
+    edge_conf['edge']['min_trade_number'] = 2
+    freqtrade = get_patched_freqtradebot(mocker, edge_conf)
+
+    freqtrade.exchange.get_fee = fee
+    edge = Edge(edge_conf, freqtrade.exchange, freqtrade.strategy)
+
+    trades = [
+        {'pair': 'TEST/BTC',
+         'stoploss': -0.9,
+         'profit_percent': '',
+         'profit_abs': '',
+         'open_date': np.datetime64('2018-10-03T00:05:00.000000000'),
+         'close_date': np.datetime64('2018-10-03T00:10:00.000000000'),
+         'open_index': 1,
+         'close_index': 1,
+         'trade_duration': '',
+         'open_rate': 15,
+         'close_rate': 17,
+         'exit_type': 'sell_signal'},
+        {'pair': 'TEST/BTC',
+         'stoploss': -0.9,
+         'profit_percent': '',
+         'profit_abs': '',
+         'open_date': np.datetime64('2018-10-03T00:20:00.000000000'),
+         'close_date': np.datetime64('2018-10-03T00:25:00.000000000'),
+         'open_index': 4,
+         'close_index': 4,
+         'trade_duration': '',
+         'open_rate': 10,
+         'close_rate': 20,
+         'exit_type': 'sell_signal'},
+        {'pair': 'TEST/BTC',
+         'stoploss': -0.9,
+         'profit_percent': '',
+         'profit_abs': '',
+         'open_date': np.datetime64('2018-10-03T00:30:00.000000000'),
+         'close_date': np.datetime64('2018-10-03T00:40:00.000000000'),
+         'open_index': 6,
+         'close_index': 7,
+         'trade_duration': '',
+         'open_rate': 26,
+         'close_rate': 134,
+         'exit_type': 'sell_signal'}
+    ]
+
+    trades_df = DataFrame(trades)
+    trades_df = edge._fill_calculable_fields(trades_df)
+    final = edge._process_expectancy(trades_df)
+
+    assert 'TEST/BTC' in final
+    assert final['TEST/BTC'].stoploss == -0.9
+    assert final['TEST/BTC'].nb_trades == len(trades_df)
+    assert round(final['TEST/BTC'].winrate, 10) == 1.0
+    assert round(final['TEST/BTC'].risk_reward_ratio, 10) == float('inf')
+    assert round(final['TEST/BTC'].expectancy, 10) == float('inf')