fixed some bugs, improved the backtesting and strategy table. Possible now to specify which features we want to use in the backtesting api

This commit is contained in:
Gert 2018-05-23 20:51:07 -07:00
parent a51746c255
commit 1b77d66e2c
6 changed files with 131 additions and 91 deletions

View File

@ -1,3 +1,4 @@
import datetime
import logging import logging
import os import os
import boto3 import boto3
@ -37,18 +38,14 @@ def backtest(event, context):
no return no return
""" """
if 'body' in event: if 'Records' in event:
event['body'] = json.loads(event['body']) for x in event['Records']:
if 'Sns' in x and 'Message' in x['Sns']:
event['body'] = json.loads(x['Sns']['Message'])
name = event['body']['name'] name = event['body']['name']
user = event['body']['user'] user = event['body']['user']
# technically we can get all these from teh strategy table
stake_currency = event['body']['stake_currency'].upper()
asset = event['body']['asset']
exchange = event['body']['exchange']
assets = list(map(lambda x: "{}/{}".format(x, stake_currency).upper(), asset))
trade_table = get_trade_table() trade_table = get_trade_table()
table = get_strategy_table() table = get_strategy_table()
@ -61,22 +58,28 @@ def backtest(event, context):
print(response) print(response)
if "Items" in response and len(response['Items']) > 0: if "Items" in response and len(response['Items']) > 0:
today = datetime.datetime.today()
yesterday = today - datetime.timedelta(days=1)
content = response['Items'][0]['content'] content = response['Items'][0]['content']
configuration = { configuration = {
"max_open_trades": 1, "max_open_trades": 1,
"stake_currency": stake_currency, "stake_currency": response['Items'][0]['stake_currency'],
"stake_amount": 1, "stake_amount": 1,
"fiat_display_currency": "USD", "fiat_display_currency": "USD",
"unfilledtimeout": 600, "unfilledtimeout": 600,
"trailing_stop": response['Items'][0]['trailing_stop'],
"bid_strategy": { "bid_strategy": {
"ask_last_balance": 0.0 "ask_last_balance": 0.0
}, },
"exchange": { "exchange": {
"name": exchange, "name": response['Items'][0]['exchange'],
"enabled": True, "enabled": True,
"key": "key", "key": "key",
"secret": "secret", "secret": "secret",
"pair_whitelist": assets "pair_whitelist": list(
map(lambda x: "{}/{}".format(x, response['Items'][0]['stake_currency']).upper(),
response['Items'][0]['assets']))
}, },
"telegram": { "telegram": {
"enabled": False, "enabled": False,
@ -86,7 +89,7 @@ def backtest(event, context):
"initial_state": "running", "initial_state": "running",
"datadir": ".", "datadir": ".",
"experimental": { "experimental": {
"use_sell_signal": True, "use_sell_signal": response['Items'][0]['use_sell'],
"sell_profit_only": True "sell_profit_only": True
}, },
"internals": { "internals": {
@ -94,7 +97,9 @@ def backtest(event, context):
}, },
'realistic_simulation': True, 'realistic_simulation': True,
"loglevel": logging.DEBUG, "loglevel": logging.DEBUG,
"strategy": "{}:{}".format(name, content) "strategy": "{}:{}".format(name, content),
"timerange": "{}-{}".format(yesterday.strftime('%Y%m%d'), today.strftime('%Y%m%d')),
"refresh_pairs": True
} }
@ -131,7 +136,7 @@ def backtest(event, context):
raise Exception( raise Exception(
"sorry we did not find any matching strategy for user {} and name {}".format(user, name)) "sorry we did not find any matching strategy for user {} and name {}".format(user, name))
else: else:
raise Exception("no body provided") raise Exception("not a valid event: {}".format(event))
def cron(event, context): def cron(event, context):

View File

@ -186,6 +186,22 @@ def __evaluate(data):
data['stoploss'] = strat.stoploss data['stoploss'] = strat.stoploss
data['ticker'] = strat.ticker_interval data['ticker'] = strat.ticker_interval
# default variables if not provided
if 'trailing_stop' not in data:
data['trailing_stop'] = False
if 'stake_currency' not in data:
data['stake_currency'] = "USDT"
if 'use_sell' not in data:
data['use_sell'] = True
if 'exchange' not in data:
data['exchange'] = 'binance'
if 'assets' not in data:
data['assets'] = ["BTC", "ETH", "LTC"]
# force serialization to deal with decimal number # force serialization to deal with decimal number
data = json.dumps(data, use_decimal=True) data = json.dumps(data, use_decimal=True)
data = json.loads(data, use_decimal=True) data = json.loads(data, use_decimal=True)

View File

@ -13,6 +13,9 @@ def get_trade_table():
:return: :return:
""" """
if 'tradeTable' not in os.environ:
os.environ['tradeTable'] = "FreqTradeTable"
table_name = os.environ['tradeTable'] table_name = os.environ['tradeTable']
existing_tables = boto3.client('dynamodb').list_tables()['TableNames'] existing_tables = boto3.client('dynamodb').list_tables()['TableNames']
if table_name not in existing_tables: if table_name not in existing_tables:
@ -55,6 +58,9 @@ def get_strategy_table():
provides us access to the strategy table and if it doesn't exists creates it for us provides us access to the strategy table and if it doesn't exists creates it for us
:return: :return:
""" """
if 'strategyTable' not in os.environ:
os.environ['strategyTable'] = "FreqStrategyTable"
table_name = os.environ['strategyTable'] table_name = os.environ['strategyTable']
existing_tables = boto3.client('dynamodb').list_tables()['TableNames'] existing_tables = boto3.client('dynamodb').list_tables()['TableNames']
@ -62,7 +68,7 @@ def get_strategy_table():
if table_name not in existing_tables: if table_name not in existing_tables:
try: try:
db.create_table( db.create_table(
TableName=os.environ[table_name], TableName=table_name,
KeySchema=[ KeySchema=[
{ {
'AttributeName': 'user', 'AttributeName': 'user',

View File

@ -1,5 +1,7 @@
import os
from base64 import urlsafe_b64encode from base64 import urlsafe_b64encode
import boto3
import pytest import pytest
import simplejson as json import simplejson as json
from freqtrade.aws.backtesting_lambda import backtest, cron from freqtrade.aws.backtesting_lambda import backtest, cron
@ -64,15 +66,21 @@ class MyFancyTestStrategy(IStrategy):
"body": json.dumps(request) "body": json.dumps(request)
}, {}) }, {})
# build sns request
request = { request = {
"user": "GCU4LW2XXZW3A3FM2XZJTEJHNWHTWDKY2DIJLCZJ5ULVZ4K7LZ7D23TG", "user": "GCU4LW2XXZW3A3FM2XZJTEJHNWHTWDKY2DIJLCZJ5ULVZ4K7LZ7D23TG",
"name": "MyFancyTestStrategy", "name": "MyFancyTestStrategy"
"stake_currency": "usdt",
"asset": ["ETH", "BTC", "XRP", "LTC"],
"exchange": "binance"
} }
backtest({"body": json.dumps(request)}, {}) backtest({
"Records": [
{
"Sns": {
"Subject": "backtesting",
"Message": json.dumps(request)
}
}]
}, {})
def test_cron(lambda_context): def test_cron(lambda_context):
@ -135,4 +143,7 @@ class MyFancyTestStrategy(IStrategy):
}, {}) }, {})
print("evaluating cron job") print("evaluating cron job")
cron({}, {}) cron({}, {})
#TODO test receiving of message some how

View File

@ -628,13 +628,15 @@ def lambda_context():
lamb.start() lamb.start()
session = boto3.session.Session() session = boto3.session.Session()
client = session.client('sns')
dynamodb = boto3.resource('dynamodb')
os.environ["strategyTable"] = "StrategyTable" os.environ["strategyTable"] = "StrategyTable"
os.environ["tradeTable"] = "TradeTable" os.environ["tradeTable"] = "TradeTable"
os.environ["topic"] = "UnitTestTopic" os.environ["topic"] = "UnitTestTopic"
client = session.client('sns')
client.create_topic(Name=os.environ["topic"])
dynamodb = boto3.resource('dynamodb')
import responses import responses
# do not mock requests to these urls # do not mock requests to these urls

View File

@ -490,7 +490,7 @@ def test_processed(default_conf, mocker) -> None:
def test_backtest_pricecontours(default_conf, fee, mocker) -> None: def test_backtest_pricecontours(default_conf, fee, mocker) -> None:
mocker.patch('freqtrade.optimize.backtesting.exchange.get_fee', fee) mocker.patch('freqtrade.optimize.backtesting.exchange.get_fee', fee)
tests = [['raise', 17], ['lower', 0], ['sine', 17]] tests = [['raise', 17], ['lower', 0], ['sine', 16]]
for [contour, numres] in tests: for [contour, numres] in tests:
simple_backtest(default_conf, contour, numres, mocker) simple_backtest(default_conf, contour, numres, mocker)