def get_xy_parameter_for_replay_list(tick_list: list, replay_process: str): x = [tick.time_stamp for tick in tick_list] y = [] for tick in tick_list: y_value_dict = { TSP.WATCHING: tick.watch_breakout_value, TSP.BUYING: tick.breakout_value, TSP.SELLING: tick.limit_value, TSP.RE_BUYING: tick.limit_value } y.append(MyMath.round_smart(y_value_dict[replay_process])) # y = [round(tick.breakout_value, 4) if for_buying else round(tick.limit_value, 4) for tick in tick_list] for tick in reversed(tick_list): x.append(tick.time_stamp) y_value_dict = { TSP.WATCHING: tick.watch_wrong_breakout_value, TSP.BUYING: tick.wrong_breakout_value, TSP.SELLING: tick.stop_loss_value, TSP.RE_BUYING: tick.stop_loss_value } y.append(MyMath.round_smart(y_value_dict[replay_process])) # y.append(round(tick.wrong_breakout_value, 4) if for_buying else round(tick.stop_loss_value, 4)) # print('list(zip(x, y))={}'.format(list(zip(x, y)))) return list(zip(x, y))
def get_markdown_text_for_last_wave_tick(self, volume_mean=0, period=PRD.INTRADAY): prev_tick = self.tick_list[-2] actual_tick = self.tick_list[-1] prefix = actual_tick.time if period == PRD.INTRADAY else actual_tick.date forecast_volume = MyMath.round_smart( actual_tick.get_forecast_volume(self.tick_distance_in_seconds)) if prev_tick.volume == 0: volume_change_against_last = 0 else: volume_change_against_last = MyMath.round_smart( forecast_volume / prev_tick.volume * 100 - 100) if volume_mean == 0: forecast_values = '{} ({:+.0f} %)'.format( forecast_volume, volume_change_against_last) else: volume_change_against_mean = MyMath.round_smart(forecast_volume / volume_mean * 100 - 100) forecast_values = '{} ({:+.0f} % / {:+.0f} %)'.format( forecast_volume, volume_change_against_mean, volume_change_against_last) return '**{}:** open={}, close={}, volume={}, volume forecast={}'. \ format(prefix, actual_tick.open, actual_tick.close, actual_tick.volume, forecast_values)
def get_lower_value(self, f_var: float, with_smart_rounding=False): if with_smart_rounding: if f_var < self.tick_for_helper.f_var: return MyMath.round_smart(self._f_lower(f_var)) return MyMath.round_smart(self._h_lower(f_var)) if f_var < self.tick_for_helper.f_var: return round(self._f_lower(f_var), 4) return round(self._h_lower(f_var), 4)
def get_upper_value(self, f_var: int, with_smart_rounding=False): if with_smart_rounding or True: if f_var < self.tick_for_helper.f_var: return MyMath.round_smart(self._f_upper(f_var)) return MyMath.round_smart(self._h_upper(f_var)) if f_var < self.tick_for_helper.f_var: return round(self._f_upper(f_var), 4) return round(self._h_upper(f_var), 4)
def __get_retracement_predictor_value__(self) -> float: if self.valid_wave is None: return 0 fc_value_regression = self.retracement_end_parameters_regression[1] fc_value_classifier = self.retracement_end_parameters_classifier[1] min_fc_value = min(fc_value_regression, fc_value_classifier) max_fc_value = max(fc_value_regression, fc_value_classifier) # print('min_fc_value={}, max_fc_value={}'.format(min_fc_value, max_fc_value)) return MyMath.round_smart(min_fc_value) if self.pattern_type == FT.FIBONACCI_DESC \ else MyMath.round_smart(max_fc_value)
def __calculate_thresholds__(self): q75, q25 = np.percentile(self._values, [75, 25]) iqr = q75 - q25 self._bottom_threshold_iqr = MyMath.round_smart(q25 - 1.5 * iqr) self._top_threshold_iqr = MyMath.round_smart(q75 + 1.5 * iqr) if len(self._values) <= 4: self._bottom_threshold = self._bottom_threshold_iqr self._top_threshold = self._top_threshold_iqr else: self._bottom_threshold = MyMath.round_smart( np.percentile(self._values, self._threshold_pct)) self._top_threshold = MyMath.round_smart( np.percentile(self._values, 100 - self._threshold_pct))
def __is_f_param_boundary_compliant__(self, f_param: np.poly1d, f_param_boundary: np.poly1d) -> bool: offset = self.tick_list[0].f_var slope_dec_main = MyPoly1d.get_slope_in_decimal_percentage( f_param, offset, self.length) slope_dec_bound = MyPoly1d.get_slope_in_decimal_percentage( f_param_boundary, offset, self.length) if f_param(offset) > f_param_boundary(offset): slope_main_bound = MyMath.round_smart(slope_dec_main - slope_dec_bound) else: slope_main_bound = MyMath.round_smart(slope_dec_bound - slope_dec_main) return slope_main_bound < 0.04 # we don't accept wide opening patterns
def __get_mean_forecast_wave_end_pct__(self): if self.are_valid_waves_available: return MyMath.round_smart( statistics.mean([ wave.forecast_wave_end_pct for wave in self.valid_wave_list ]) * 100) return 0
def set_fee_amount(self, fee_value: float, as_pct=False): amount = self.original_amount if self.executed_amount == 0 else self.executed_amount if as_pct: self._fee_amount = MyMath.round_smart(self.price * amount * fee_value / 100) else: self._fee_amount = fee_value
def __get_mean_forecast_retracement_pct__(self) -> float: if self.are_valid_waves_available: retracement_pct_list = [ wave.forecast_value_retracement_pct for wave in self.valid_wave_list ] return MyMath.round_smart(statistics.mean(retracement_pct_list)) return 0
def get_xy_parameter_for_tick_function_list(tick_list: list, func_list, closed: bool = True): x = [tick.f_var for tick in tick_list] y = [ MyMath.round_smart(func(tick_list[ind].f_var)) for ind, func in enumerate(func_list) ] return list(zip(x, y))
def __get_rounded_value__(key, value): if key in [SLDC.PRICE, SLDC.PRICE_SINGLE, SLDC.PRICE_ORIGINAL]: try: return MyMath.round_smart(value) except: print('SalesmanDataDictionary: Error for {}={}'.format( key, value)) return 0 return value
def get_tolerance_pct_values(self): if self.pattern_data.df.shape[0] <= 1: print( 'get_tolerance_pct_values: we have only one row - returning 0, 0, 0' ) return 0, 0, 0 mean_hl = MyMath.round_smart(self.pattern_data.df[CN.MEAN_HL].mean()) if mean_hl == 0 or mean_hl == math.nan: return 0, 0, 0 std_dev_mean_hl = MyMath.round_smart( self.pattern_data.df[CN.MEAN_HL].std()) base_tolerance_pct = MyMath.round_smart(std_dev_mean_hl / mean_hl) tolerance_pct = base_tolerance_pct / 5 tolerance_pct_equal = tolerance_pct / 2 tolerance_pct_buying = 0 # tolerance_pct / 2 print( 'tolerance_pct={:.2f}%, tolerance_pct_equal={:.2f}%, tolerance_pct_buying={:.2f}%' .format(tolerance_pct * 100, tolerance_pct_equal * 100, tolerance_pct_buying * 100)) return tolerance_pct, tolerance_pct_equal, tolerance_pct_buying
def __init__(self, api: PatternBreakoutApi): self.sys_config = api.sys_config self.function_cont = api.function_cont self.constraints = api.constraints self.tick_previous = api.tick_previous self.tick_breakout = api.tick_breakout self.volume_mean_part_entry = api.volume_mean_for_breakout self.volume_forecast = api.volume_forecast self.breakout_date = self.tick_breakout.date self.volume_change_pct = MyMath.divide(self.tick_breakout.volume, self.tick_previous.volume, 2, 0) self.tolerance_pct = self.constraints.tolerance_pct self.bound_upper = MyMath.round_smart( self.function_cont.get_upper_value(self.tick_breakout.f_var)) self.bound_lower = MyMath.round_smart( self.function_cont.get_lower_value(self.tick_breakout.f_var)) self.pattern_breadth = MyMath.round_smart(self.bound_upper - self.bound_lower) self.tolerance_range = MyMath.round_smart(self.pattern_breadth * self.tolerance_pct) self.limit_upper = MyMath.round_smart(self.bound_upper + self.tolerance_range) self.limit_lower = MyMath.round_smart(self.bound_lower - self.tolerance_range) if api.forecast_breakout_direction == FD.NONE: self.breakout_direction = self.__get_breakout_direction__() else: self.breakout_direction = api.forecast_breakout_direction self.sign = 1 if self.breakout_direction == FD.ASC else -1 self.check_dict = {}
def __calculate_variables__(self, by_iqr=False): self._min_values = MyMath.round_smart(min(self._values)) self._max_values = MyMath.round_smart(max(self._values)) self._mean_values = MyMath.round_smart(statistics.mean(self._values)) self.__calculate_thresholds__() for value in self._values: if not self.is_value_outlier(value): self._values_without_outliers.append(value) if not self.is_value_iqr_outlier(value): self._values_without_iqr_outliers.append(value) if len(self._values_without_outliers) == 0: self._mean_values_without_outliers = 0 else: self._mean_values_without_outliers = \ MyMath.round_smart(statistics.mean(self._values_without_outliers)) if len(self._values_without_iqr_outliers) == 0: self._mean_values_without_iqr_outliers = 0 else: self._mean_values_without_iqr_outliers = \ MyMath.round_smart(statistics.mean(self._values_without_iqr_outliers))
def __get_mean_parameters_from_xy_parameter_list__( xy_parameters_list: list): # we get a list of ...[(1556661600, 215.3), (1557375012, 154.46), (1559296128, 181.64), (1556661600, 215.3)] xy_parameters_return = [] for idx in (0, 1, 2): ts_list = [ xy_parameters[idx][0] for xy_parameters in xy_parameters_list ] value_list = [ xy_parameters[idx][1] for xy_parameters in xy_parameters_list ] ts_mean = int(statistics.mean(ts_list)) value_mean = MyMath.round_smart(statistics.mean(value_list)) xy_parameters_return.append((ts_mean, value_mean)) # print('xy_parameters_return={}'.format(xy_parameters_return)) return xy_parameters_return
def __init__(self, ticker_id: str, bid: float, ask: float, last_price: float, low: float, high: float, vol: float, ts: int): self.ticker_id = ticker_id self.bid = MyMath.round_smart(bid) self.ask = MyMath.round_smart(ask) self.last_price = MyMath.round_smart(last_price) self.low = MyMath.round_smart(low) self.high = MyMath.round_smart(high) self.vol = MyMath.round_smart(vol) self.time_stamp = round(ts)
def get_simple_moving_average(self, elements: int = 0, ts_breakout=0, default_value=0): """ The simple moving average is calculated in this way: a) For all ticks before the breakout we take the lower bound value = default_value b) For all others we take the low """ base_list = self.tick_list if elements == 0 else self.tick_list[ -elements:] base_list_reversed = base_list[::-1] value_list = [] for tick in base_list_reversed: if tick.time_stamp < ts_breakout: value_list.append(default_value) else: value_list.append(tick.open) return MyMath.round_smart(np.average(value_list))
def __get_df_adjusted_to_aggregation__( self, df: pd.DataFrame): # is called only for PRD.INTRADAY source_aggregation = int((df.index[1] - df.index[0]) / 60) if source_aggregation == self.aggregation: return df source_rows_per_aggregation = int(self.aggregation / source_aggregation) row_list = [] value_dict = { CN.OPEN: 0, CN.LOW: 0, CN.HIGH: 0, CN.CLOSE: 0, CN.VOL: 0 } row_for_aggregation = {} row_counter_per_aggregation = 0 for index, row in df.iterrows(): if row_counter_per_aggregation == 0: row_for_aggregation = copy.deepcopy(row) for value_index in value_dict: value_dict[value_index] = row[ value_index] # default values for new aggretation else: value_dict[CN.LOW] = min(value_dict[CN.LOW], row[CN.LOW]) value_dict[CN.HIGH] = max(value_dict[CN.HIGH], row[CN.HIGH]) value_dict[CN.CLOSE] = row[CN.CLOSE] value_dict[CN.VOL] += row[CN.VOL] row_counter_per_aggregation += 1 if row_counter_per_aggregation == source_rows_per_aggregation or index == df.index[ -1]: for value_index, value in value_dict.items(): row_for_aggregation[value_index] = round(value, 0) \ if value_index == CN.VOL else MyMath.round_smart(value) row_list.append(row_for_aggregation) row_counter_per_aggregation = 0 df_new = pd.DataFrame(row_list) return df_new
def get_annotation_text_as_dict(self, prediction_text_dict: dict) -> dict: std_dev = MyMath.round_smart(self.df[CN.CLOSE].std()) f_upper_percent, f_lower_percent, f_reg_percent = self.get_slope_values() if self.sys_config.period == PRD.INTRADAY: date_str_first = self.tick_first.time_str_for_f_var date_str_last = self.tick_last.time_str_for_f_var else: date_str_first = self.tick_first.date_str_for_f_var date_str_last = self.tick_last.date_str_for_f_var pattern = '{}: {} - {} ({})'.format(self.pattern_type, date_str_first, date_str_last, len(self.tick_list)) if self.pattern_type in [FT.TKE_TOP, FT.HEAD_SHOULDER]: gradients = 'L={:.1f}%, Reg={:.1f}%'.format(f_lower_percent, f_reg_percent) height = '{:.2f}, Std_dev={:.2f}, Std_regression={:.2f}'.format(self.height, std_dev, self.std_regression) elif self.pattern_type in [FT.TKE_BOTTOM, FT.HEAD_SHOULDER_BOTTOM]: gradients = 'U={:.1f}%, Reg={:.1f}%'.format(f_upper_percent, f_reg_percent) height = '{:.2f}, Std_dev={:.2f}, Std_regression={:.2f}'.format(self.height, std_dev, self.std_regression) else: gradients = 'U={:.1f}%, L={:.1f}%, Reg={:.1f}%'.format(f_upper_percent, f_lower_percent, f_reg_percent) height = '{:.2f}, Max={:.2f}, Min={:.2f}, Std_dev={:.2f}, Std_regression={:.2f}'.format( self.height, self.distance_max, self.distance_min, std_dev, self.std_regression) return_dict = {'Pattern': pattern, 'Gradients': gradients, 'Height': height} if self.breakout is None: return_dict['Breakout'] = 'not yet' else: return_dict['Breakout'] = '{}'.format(self.breakout.get_details_for_annotations()) self.__add_expected_trading_end_to_dict__(return_dict) return_dict['Range position'] = '{}'.format(self.pattern_range.position_list) return_dict['Value series positions'] = self._series_hit_details return_dict[PAT.BEFORE_BREAKOUT] = prediction_text_dict[PAT.BEFORE_BREAKOUT] # return_dict[PAT.BEFORE_BREAKOUT_DETAILS] = prediction_text_dict[PAT.BEFORE_BREAKOUT_DETAILS] if self.breakout or PAT.AFTER_BREAKOUT in prediction_text_dict: return_dict[PAT.AFTER_BREAKOUT] = prediction_text_dict[PAT.AFTER_BREAKOUT] if PAT.RETRACEMENT in prediction_text_dict: return_dict[PAT.RETRACEMENT] = prediction_text_dict[PAT.RETRACEMENT] return return_dict
def __calculate_new_rows_for_df_index__(self): for index, date_str in enumerate(self._date_list): counter = 0 value_dict = { CN.OPEN: 0, CN.LOW: 0, CN.HIGH: 0, CN.CLOSE: 0, CN.VOL: 0 } row_for_date = {} for symbol, df_adjusted in self._adjusted_member_symbol_df_dict.items( ): if counter == 0: row_for_date = copy.deepcopy(df_adjusted.iloc[index]) row_for_date[CN.SYMBOL] = self._index row = df_adjusted.iloc[index] for value_index in value_dict: value_dict[value_index] += row[value_index] counter += 1 row_for_date[CN.TIMESTAMP] = int(row_for_date[CN.TIMESTAMP]) for value_index, value in value_dict.items(): row_for_date[value_index] = round( value, 0) if value_index == CN.VOL else MyMath.round_smart(value) if self._save_to_database: insert_handler = StockInsertHandler(self._index, PRD.DAILY, 1) insert_handler.add_data_frame_row(row_for_date[CN.TIMESTAMP], row_for_date) self._db_stock.insert_stocks_data( insert_handler.input_dict_list) self._df_index = self._df_index.append(row_for_date, ignore_index=True) print('Added to df_index: {}'.format(date_str))
def min(self): return MyMath.round_smart(np.min([tick.low for tick in self.tick_list]))
def value_total(self): return MyMath.round_smart(self.price * self.executed_amount + self.fee_amount)
def get_xy_for_tick_list_and_function(tick_list: list, func): x = [tick.f_var for tick in tick_list] y = [MyMath.round_smart(func(tick.f_var)) for tick in tick_list] return list(zip(x, y))
def low_buy_box(self): # return self.close return MyMath.round_smart((self.body_low + self.low) / 2)
def mean(self): return MyMath.round_smart((self.high + self.low) / 2)
def volume(self): return MyMath.round_smart(self.tick[CN.VOL])
def value_range(self): return MyMath.round_smart(self.max - self.min)
def mean(self): return MyMath.round_smart( np.mean([tick.mean for tick in self.tick_list])[0])
def max(self): return MyMath.round_smart( np.max([tick.high for tick in self.tick_list]))