From b4d6e2c28946ac7c2dcea3aefff9bd7762e07128 Mon Sep 17 00:00:00 2001 From: Gert Wohlgemuth Date: Mon, 21 May 2018 16:52:12 -0700 Subject: [PATCH] working on backtesting --- freqtrade/aws/backtesting_lambda.py | 86 +++++++++++++++++++-- freqtrade/aws/strategy.py | 15 ++++ freqtrade/optimize/backtesting.py | 18 +++-- freqtrade/tests/aws/test_backtest.py | 2 +- freqtrade/tests/aws/test_strategy_lambda.py | 2 +- serverless.yml | 18 ++++- 6 files changed, 128 insertions(+), 13 deletions(-) diff --git a/freqtrade/aws/backtesting_lambda.py b/freqtrade/aws/backtesting_lambda.py index a9071e6a3..7a9754c1e 100644 --- a/freqtrade/aws/backtesting_lambda.py +++ b/freqtrade/aws/backtesting_lambda.py @@ -1,5 +1,10 @@ +import logging + +from freqtrade.arguments import Arguments +from freqtrade.configuration import Configuration from freqtrade.optimize.backtesting import Backtesting + def backtest(event, context): """ this method is running on the AWS server @@ -11,8 +16,12 @@ def backtest(event, context): :param event: { 'strategy' : 'url handle where we can find the strategy' - 'pair' : ' pair to backtest, BTC_ETH as example' - 'timeframe' : 'how long should we backtest for, 0-100 as example for the last 100 ticks' + 'stake_currency' : 'our desired stake currency' + 'asset' : '[] asset we are interested in. If empy, we fill use a default list + 'username' : user who's strategy should be evaluated + 'name' : name of the strategy we want to evaluate + 'exchange' : name of the exchange we should be using + } :param context: standard AWS context, so pleaes ignore for now! @@ -20,14 +29,77 @@ def backtest(event, context): no return """ - backtesting = Backtesting() - backtesting.start() + name = "TestStrategy" + user = "12345678" + stake_currency = "USDT" + asset = ["ETH", "BTC"] + exchange = "binance" + assets = list(map(lambda x: "{}/{}".format(x, stake_currency).upper(), asset)) + + configuration = { + "max_open_trades": 1, + "stake_currency": stake_currency, + "stake_amount": 0.001, + "fiat_display_currency": "USD", + "unfilledtimeout": 600, + "bid_strategy": { + "ask_last_balance": 0.0 + }, + "exchange": { + "name": "bittrex", + "enabled": True, + "key": "key", + "secret": "secret", + "pair_whitelist": assets + }, + "telegram": { + "enabled": False, + "token": "token", + "chat_id": "0" + }, + "initial_state": "running", + "datadir": ".", + "experimental": { + "use_sell_signal": True, + "sell_profit_only": True + }, + "internals": { + "process_throttle_secs": 5 + }, + 'realistic_simulation': True, + "loglevel": logging.DEBUG + + } + + print("generated configuration") + print(configuration) + + print("initialized backtesting") + backtesting = Backtesting(configuration) + result = backtesting.start() + print("finished test") + + print(result) + print("persist data in dynamo") + + for index, row in result.iterrows(): + item = { + "id": "{}.{}:{}".format(user, name, row['pair']), + "pair": row['pair'], + "profit": row['profit'], + "loss": row['loss'], + "duration": row['avg duration'], + "avg profit": row['avg profit %'], + "total profit": row['total profit {}'.format(stake_currency)] + + } + + print(item) pass def submit(event, context): - """ this functions submits a new strategy to the backtesting queue @@ -37,3 +109,7 @@ def submit(event, context): :return: """ pass + + +if __name__ == '__main__': + backtest({}, {}) diff --git a/freqtrade/aws/strategy.py b/freqtrade/aws/strategy.py index 75e7ed60d..90a8d801f 100644 --- a/freqtrade/aws/strategy.py +++ b/freqtrade/aws/strategy.py @@ -186,3 +186,18 @@ def submit(event, context): "statusCode": result['ResponseMetadata']['HTTPStatusCode'], "body": json.dumps(result) } + + +def submit_github(event, context): + """ + there has been a push to our github repository, so let's + update all the strategies. + + The user account will be the provided secret + + :param event: + :param context: + :return: + """ + + print(event) \ No newline at end of file diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 376730d0f..9649f15c4 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -31,6 +31,7 @@ class Backtesting(object): backtesting = Backtesting(config) backtesting.start() """ + def __init__(self, config: Dict[str, Any]) -> None: self.config = config self.analyze = None @@ -71,15 +72,19 @@ class Backtesting(object): for frame in data.values() ] return min(timeframe, key=operator.itemgetter(0))[0], \ - max(timeframe, key=operator.itemgetter(1))[1] + max(timeframe, key=operator.itemgetter(1))[1] def _generate_text_table(self, data: Dict[str, Dict], results: DataFrame) -> str: """ Generates and returns a text table for the given backtest data and the results dataframe :return: pretty printed table with tabulate as str """ - stake_currency = self.config.get('stake_currency') + floatfmt, headers, tabular_data = self.aggregate(data, results) + return tabulate(tabular_data, headers=headers, floatfmt=floatfmt) + + def aggregate(self, data, results): + stake_currency = self.config.get('stake_currency') floatfmt = ('s', 'd', '.2f', '.8f', '.1f') tabular_data = [] headers = ['pair', 'buy count', 'avg profit %', @@ -95,7 +100,6 @@ class Backtesting(object): len(result[result.profit_BTC > 0]), len(result[result.profit_BTC < 0]) ]) - # Append Total tabular_data.append([ 'TOTAL', @@ -106,7 +110,7 @@ class Backtesting(object): len(results[results.profit_BTC > 0]), len(results[results.profit_BTC < 0]) ]) - return tabulate(tabular_data, headers=headers, floatfmt=floatfmt) + return floatfmt, headers, tabular_data def _get_sell_trade_entry( self, pair: str, buy_row: DataFrame, @@ -213,7 +217,7 @@ class Backtesting(object): labels = ['currency', 'profit_percent', 'profit_BTC', 'duration'] return DataFrame.from_records(trades, columns=labels) - def start(self) -> None: + def start(self): """ Run a backtesting end-to-end :return: None @@ -282,6 +286,10 @@ class Backtesting(object): ) ) + # return date for data storage + temp = self.aggregate(data, results) + return DataFrame(data=temp[2][:-1], columns=temp[1]) + def setup_configuration(args: Namespace) -> Dict[str, Any]: """ diff --git a/freqtrade/tests/aws/test_backtest.py b/freqtrade/tests/aws/test_backtest.py index bd5ab4fce..cd27abad3 100644 --- a/freqtrade/tests/aws/test_backtest.py +++ b/freqtrade/tests/aws/test_backtest.py @@ -3,5 +3,5 @@ import pytest from freqtrade.aws.backtesting_lambda import backtest -def test_backtest(lambda_context): +def test_backtest(): backtest({}, {}) diff --git a/freqtrade/tests/aws/test_strategy_lambda.py b/freqtrade/tests/aws/test_strategy_lambda.py index fa62b66f6..b436a62d6 100644 --- a/freqtrade/tests/aws/test_strategy_lambda.py +++ b/freqtrade/tests/aws/test_strategy_lambda.py @@ -5,7 +5,7 @@ import freqtrade.aws.strategy as aws def test_strategy(lambda_context): """ - very uggly long test + very ugly long test :param lambda_context: :return: diff --git a/serverless.yml b/serverless.yml index cd9b8717c..d6ea7920d 100644 --- a/serverless.yml +++ b/serverless.yml @@ -162,7 +162,7 @@ functions: handler: freqtrade/aws/strategy.submit events: - http: - path: submit + path: strategies/submit method: post cors: true @@ -170,6 +170,22 @@ functions: topic: ${self:custom.snsTopic} strategyTable: ${self:custom.strategyTable} + + #submits a new strategy to the system + submit_github: + memorySize: 128 + handler: freqtrade/aws/strategy.submit_github + events: + - http: + path: strategies/submit/github + method: post + cors: true + + environment: + topic: ${self:custom.snsTopic} + strategyTable: ${self:custom.strategyTable} + + #TODO #backtests the strategy backtest: