hmm
This commit is contained in:
parent
4e68362d46
commit
a8b62a21cc
@ -190,7 +190,6 @@ class Backtesting(object):
|
|||||||
return btr
|
return btr
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@profile
|
|
||||||
def backtest(self, args: Dict) -> DataFrame:
|
def backtest(self, args: Dict) -> DataFrame:
|
||||||
"""
|
"""
|
||||||
Implements backtesting functionality
|
Implements backtesting functionality
|
||||||
@ -233,7 +232,13 @@ class Backtesting(object):
|
|||||||
last_bslap_results = bslap_results
|
last_bslap_results = bslap_results
|
||||||
bslap_results = last_bslap_results + bslap_pair_results
|
bslap_results = last_bslap_results + bslap_pair_results
|
||||||
|
|
||||||
|
# Switch List of Trade Dicts (bslap_results) to Dataframe
|
||||||
|
# Fill missing, calculable columns, profit, duration , abs etc.
|
||||||
bslap_results_df = DataFrame(bslap_results, columns=BacktestResult._fields)
|
bslap_results_df = DataFrame(bslap_results, columns=BacktestResult._fields)
|
||||||
|
bslap_results_df = self.vector_fill_results_table(bslap_results_df)
|
||||||
|
|
||||||
|
print(bslap_results_df.dtypes)
|
||||||
|
|
||||||
return bslap_results_df
|
return bslap_results_df
|
||||||
|
|
||||||
########################### Original BT loop
|
########################### Original BT loop
|
||||||
@ -283,6 +288,69 @@ class Backtesting(object):
|
|||||||
# return DataFrame.from_records(trades, columns=BacktestResult._fields)
|
# return DataFrame.from_records(trades, columns=BacktestResult._fields)
|
||||||
######################## Original BT loop end
|
######################## Original BT loop end
|
||||||
|
|
||||||
|
def vector_fill_results_table(self, bslap_results_df: DataFrame):
|
||||||
|
"""
|
||||||
|
The Results frame contains a number of columns that are calculable
|
||||||
|
from othe columns. These are left blank till all rows are added,
|
||||||
|
to be populated in single vector calls.
|
||||||
|
|
||||||
|
Columns to be populated are:
|
||||||
|
- Profit
|
||||||
|
- trade duration
|
||||||
|
- profit abs
|
||||||
|
|
||||||
|
:param bslap_results Dataframe
|
||||||
|
:return: bslap_results Dataframe
|
||||||
|
"""
|
||||||
|
import pandas as pd
|
||||||
|
debug = True
|
||||||
|
|
||||||
|
# stake and fees
|
||||||
|
stake = self.config.get('stake_amount')
|
||||||
|
# TODO grab these from the environment, do not hard set
|
||||||
|
open_fee = 0.05
|
||||||
|
close_fee = 0.05
|
||||||
|
|
||||||
|
if debug:
|
||||||
|
print("Stake is,", stake, "the sum of currency to spend per trade")
|
||||||
|
print("The open fee is", open_fee, "The close fee is", close_fee)
|
||||||
|
if debug:
|
||||||
|
from pandas import set_option
|
||||||
|
set_option('display.max_rows', 5000)
|
||||||
|
set_option('display.max_columns', 8)
|
||||||
|
pd.set_option('display.width', 1000)
|
||||||
|
pd.set_option('max_colwidth', 40)
|
||||||
|
pd.set_option('precision', 12)
|
||||||
|
|
||||||
|
# Align with BT
|
||||||
|
bslap_results_df['open_time'] = pd.to_datetime(bslap_results_df['open_time'])
|
||||||
|
bslap_results_df['close_time'] = pd.to_datetime(bslap_results_df['close_time'])
|
||||||
|
|
||||||
|
# Populate duration
|
||||||
|
bslap_results_df['trade_duration'] = bslap_results_df['close_time'] - bslap_results_df['open_time']
|
||||||
|
if debug:
|
||||||
|
print(bslap_results_df[['open_time', 'close_time', 'trade_duration']])
|
||||||
|
|
||||||
|
## Spends, Takes, Profit, Absolute Profit
|
||||||
|
# Buy Price
|
||||||
|
bslap_results_df['buy_sum'] = stake * bslap_results_df['open_rate']
|
||||||
|
bslap_results_df['buy_fee'] = bslap_results_df['buy_sum'] * open_fee
|
||||||
|
bslap_results_df['buy_spend'] = bslap_results_df['buy_sum'] + bslap_results_df['buy_fee']
|
||||||
|
# Sell price
|
||||||
|
bslap_results_df['sell_sum'] = stake * bslap_results_df['close_rate']
|
||||||
|
bslap_results_df['sell_fee'] = bslap_results_df['sell_sum'] * close_fee
|
||||||
|
bslap_results_df['sell_take'] = bslap_results_df['sell_sum'] - bslap_results_df['sell_fee']
|
||||||
|
# profit_percent
|
||||||
|
bslap_results_df['profit_percent'] = bslap_results_df['sell_take'] / bslap_results_df['buy_spend'] - 1
|
||||||
|
# Absolute profit
|
||||||
|
bslap_results_df['profit_abs'] = bslap_results_df['sell_take'] - bslap_results_df['buy_spend']
|
||||||
|
|
||||||
|
if debug:
|
||||||
|
print("\n")
|
||||||
|
print(bslap_results_df[['buy_spend', 'sell_take', 'profit_percent', 'profit_abs']])
|
||||||
|
|
||||||
|
return bslap_results_df
|
||||||
|
|
||||||
def np_get_t_open_ind(self, np_buy_arr, t_exit_ind: int):
|
def np_get_t_open_ind(self, np_buy_arr, t_exit_ind: int):
|
||||||
import utils_find_1st as utf1st
|
import utils_find_1st as utf1st
|
||||||
"""
|
"""
|
||||||
@ -301,6 +369,7 @@ class Backtesting(object):
|
|||||||
t_open_ind = t_open_ind + t_exit_ind # Align numpy index
|
t_open_ind = t_open_ind + t_exit_ind # Align numpy index
|
||||||
return t_open_ind
|
return t_open_ind
|
||||||
|
|
||||||
|
@profile
|
||||||
def backslap_pair(self, ticker_data, pair):
|
def backslap_pair(self, ticker_data, pair):
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
import numpy as np
|
import numpy as np
|
||||||
@ -316,19 +385,10 @@ class Backtesting(object):
|
|||||||
# Read Stop Loss Values and Stake
|
# Read Stop Loss Values and Stake
|
||||||
stop = self.stop_loss_value
|
stop = self.stop_loss_value
|
||||||
p_stop = (stop + 1) # What stop really means, e.g 0.01 is 0.99 of price
|
p_stop = (stop + 1) # What stop really means, e.g 0.01 is 0.99 of price
|
||||||
stake = self.config.get('stake_amount')
|
|
||||||
|
|
||||||
# Set fees
|
|
||||||
# TODO grab these from the environment, do not hard set
|
|
||||||
# Fees
|
|
||||||
open_fee = 0.05
|
|
||||||
close_fee = 0.05
|
|
||||||
|
|
||||||
if debug:
|
if debug:
|
||||||
print("Stop is ", stop, "value from stragey file")
|
print("Stop is ", stop, "value from stragey file")
|
||||||
print("p_stop is", p_stop, "value used to multiply to entry price")
|
print("p_stop is", p_stop, "value used to multiply to entry price")
|
||||||
print("Stake is,", stake, "the sum of currency to spend per trade")
|
|
||||||
print("The open fee is", open_fee, "The close fee is", close_fee)
|
|
||||||
|
|
||||||
if debug:
|
if debug:
|
||||||
from pandas import set_option
|
from pandas import set_option
|
||||||
@ -395,6 +455,12 @@ class Backtesting(object):
|
|||||||
# buy 0 - open 1 - close 2 - sell 3 - high 4 - low 5
|
# buy 0 - open 1 - close 2 - sell 3 - high 4 - low 5
|
||||||
np_bslap = np.array(bslap[['buy', 'open', 'close', 'sell', 'high', 'low']])
|
np_bslap = np.array(bslap[['buy', 'open', 'close', 'sell', 'high', 'low']])
|
||||||
|
|
||||||
|
# Build a numpy list of date-times.
|
||||||
|
# We use these when building the trade
|
||||||
|
# The rationale is to address a value from a pandas cell is thousands of
|
||||||
|
# times more expensive. Processing time went X25 when trying to use any data from pandas
|
||||||
|
np_bslap_dates = bslap['date'].values
|
||||||
|
|
||||||
loop: int = 0 # how many time around the loop
|
loop: int = 0 # how many time around the loop
|
||||||
t_exit_ind = 0 # Start loop from first index
|
t_exit_ind = 0 # Start loop from first index
|
||||||
t_exit_last = 0 # To test for exit
|
t_exit_last = 0 # To test for exit
|
||||||
@ -660,6 +726,10 @@ class Backtesting(object):
|
|||||||
Add trade to backtest looking results list of dicts
|
Add trade to backtest looking results list of dicts
|
||||||
Loop back to look for more trades.
|
Loop back to look for more trades.
|
||||||
"""
|
"""
|
||||||
|
if debug_timing:
|
||||||
|
t_t = f(st)
|
||||||
|
print("8a-IfEls", str.format('{0:.17f}', t_t))
|
||||||
|
st = s()
|
||||||
# Index will change if incandle stop or look back as close Open and Sell
|
# Index will change if incandle stop or look back as close Open and Sell
|
||||||
if t_exit_type == 'stop':
|
if t_exit_type == 'stop':
|
||||||
close_index: int = t_exit_ind + 1
|
close_index: int = t_exit_ind + 1
|
||||||
@ -668,39 +738,56 @@ class Backtesting(object):
|
|||||||
else:
|
else:
|
||||||
close_index: int = t_exit_ind + 1
|
close_index: int = t_exit_ind + 1
|
||||||
|
|
||||||
# Munge the date / delta (bt already date formats...just subract)
|
if debug_timing:
|
||||||
trade_start = bslap.iloc[t_open_ind + 1]['date']
|
t_t = f(st)
|
||||||
trade_end = bslap.iloc[close_index]['date']
|
print("8b-Index", str.format('{0:.17f}', t_t))
|
||||||
# def __datetime(date_str):
|
st = s()
|
||||||
# return datetime.strptime(date_str, '%Y-%m-%d %H:%M:%S+00:00')
|
|
||||||
trade_mins = (trade_end - trade_start).total_seconds() / 60
|
|
||||||
|
|
||||||
# Profit ABS.
|
# # Profit ABS.
|
||||||
# sumrecieved((rate * numTokens) * fee) - sumpaid ((rate * numTokens) * fee)
|
# # sumrecieved((rate * numTokens) * fee) - sumpaid ((rate * numTokens) * fee)
|
||||||
sumpaid: float = (np_trade_enter_price * stake)
|
# sumpaid: float = (np_trade_enter_price * stake)
|
||||||
sumpaid_fee: float = sumpaid * open_fee
|
# sumpaid_fee: float = sumpaid * open_fee
|
||||||
sumrecieved: float = (np_trade_exit_price * stake)
|
# sumrecieved: float = (np_trade_exit_price * stake)
|
||||||
sumrecieved_fee: float = sumrecieved * close_fee
|
# sumrecieved_fee: float = sumrecieved * close_fee
|
||||||
profit_abs: float = sumrecieved - sumpaid - sumpaid_fee - sumrecieved_fee
|
# profit_abs: float = sumrecieved - sumpaid - sumpaid_fee - sumrecieved_fee
|
||||||
|
|
||||||
|
if debug_timing:
|
||||||
|
t_t = f(st)
|
||||||
|
print("8d---ABS", str.format('{0:.17f}', t_t))
|
||||||
|
st = s()
|
||||||
|
|
||||||
|
# Build trade dictionary
|
||||||
|
## In general if a field can be calculated later from other fields leave blank here
|
||||||
|
## Its X(numer of trades faster) to calc all in a single vector than 1 trade at a time
|
||||||
|
|
||||||
# build trade dictionary
|
|
||||||
bslap_result["pair"] = pair
|
bslap_result["pair"] = pair
|
||||||
bslap_result["profit_percent"] = (np_trade_exit_price - np_trade_enter_price) / np_trade_enter_price
|
bslap_result["profit_percent"] = "1" # To be 1 vector calc across trades when loop complete
|
||||||
bslap_result["profit_abs"] = round(profit_abs, 15)
|
bslap_result["profit_abs"] = "1" # To be 1 vector calc across trades when loop complete
|
||||||
bslap_result["open_time"] = trade_start
|
bslap_result["open_time"] = np_bslap_dates[t_open_ind + 1] # use numpy array, pandas 20x slower
|
||||||
bslap_result["close_time"] = trade_end
|
bslap_result["close_time"] = np_bslap_dates[close_index] # use numpy array, pandas 20x slower
|
||||||
bslap_result["open_index"] = t_open_ind + 2 # +1 between np and df, +1 as we buy on next.
|
bslap_result["open_index"] = t_open_ind + 2 # +1 between np and df, +1 as we buy on next.
|
||||||
bslap_result["close_index"] = close_index
|
bslap_result["close_index"] = close_index
|
||||||
bslap_result["trade_duration"] = trade_mins
|
bslap_result["trade_duration"] = "1" # To be 1 vector calc across trades when loop complete
|
||||||
bslap_result["open_at_end"] = False
|
bslap_result["open_at_end"] = False
|
||||||
bslap_result["open_rate"] = round(np_trade_enter_price, 15)
|
bslap_result["open_rate"] = round(np_trade_enter_price, 15)
|
||||||
bslap_result["close_rate"] = round(np_trade_exit_price, 15)
|
bslap_result["close_rate"] = round(np_trade_exit_price, 15)
|
||||||
#bslap_result["exit_type"] = t_exit_type
|
bslap_result["exit_type"] = t_exit_type
|
||||||
|
|
||||||
|
if debug_timing:
|
||||||
|
t_t = f(st)
|
||||||
|
print("8e-trade", str.format('{0:.17f}', t_t))
|
||||||
|
st = s()
|
||||||
# Add trade dictionary to list
|
# Add trade dictionary to list
|
||||||
bslap_pair_results.append(bslap_result)
|
bslap_pair_results.append(bslap_result)
|
||||||
|
|
||||||
if debug:
|
if debug:
|
||||||
print(bslap_pair_results)
|
print(bslap_pair_results)
|
||||||
|
|
||||||
|
if debug_timing:
|
||||||
|
t_t = f(st)
|
||||||
|
print("8f--list", str.format('{0:.17f}', t_t))
|
||||||
|
st = s()
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Loop back to start. t_exit_last becomes where loop
|
Loop back to start. t_exit_last becomes where loop
|
||||||
will seek to open new trades from.
|
will seek to open new trades from.
|
||||||
|
Loading…
Reference in New Issue
Block a user