#ifndef LOT_CALC_MQH #define LOT_CALC_MQH #include "../setting.mqh" #define RIGAL_MOD_3 //#define RIGAL_MOD_4 class calc_lot { private: static bool is_lvl1 ( setting_t *settings, int order_count ) { return settings.multi_lots_level1 != 0 && order_count >= settings.multi_lots_level1; } static bool is_lvl2 ( setting_t *settings, int order_count ) { return settings.multi_lots_level2 != 0 && is_lvl1 ( settings, order_count ) && order_count >= settings.multi_lots_level2; } static bool is_lvl3 ( setting_t *settings, int order_count ) { return settings.multi_lots_level3 != 0 && is_lvl2 ( settings, order_count ) && order_count >= settings.multi_lots_level3; } static bool is_lvl4 ( setting_t *settings, int order_count ) { return settings.mult4 != 0 && is_lvl3 ( settings, order_count ) && order_count >= settings.mult4; } static double get_factor ( setting_t *settings, int lvl ) { double result = 1.0; if ( settings.mult_stop != 0 && settings.mult_stop < lvl ) { lvl = settings.mult_stop; } if ( is_lvl4 ( settings, lvl ) ) { result = get_factor ( settings, lvl - ( lvl - settings.mult4 + 1 ) ); int count = lvl + 1 - settings.mult4; for ( int i = 0; i < count; i++ ) { result += settings.mult4_add; } } else if ( is_lvl3 ( settings, lvl ) ) { result = get_factor ( settings, lvl - ( lvl - settings.multi_lots_level3 + 1 ) ); int count = lvl + 1 - settings.multi_lots_level3; for ( int i = 0; i < count; i++ ) { result += settings.multi_lots_level3_corr; } } else if ( is_lvl2 ( settings, lvl ) ) { result = get_factor ( settings, lvl - ( lvl - settings.multi_lots_level2 + 1 ) ); int count = lvl + 1 - settings.multi_lots_level2; for ( int i = 0; i < count; i++ ) { result += settings.multi_lots_level2_corr; } } else if ( is_lvl1 ( settings, lvl ) ) { result = settings.multi_lots_factor; } return result; } static double get_for_gap_control ( setting_t *settings, enum_order_operation_type order_type, int lvl, double last_lot, double last_price, double price ) { double step_p = layer_market::to_points ( calc_grid_step::get ( settings, lvl ) ); double distance_p = tool_order::get_distance ( order_type, price, last_price ); double lot_factor = get_factor ( settings, lvl ); if ( !calc_gap::is_gap ( settings, order_type, order_type, distance_p, step_p ) ) { return last_lot * lot_factor; } // TODO: print on every calc lot //log_info_k ( _msg_key, StringFormat ( SRC_HANDLER_BASE_DETECT_GAP, dtos ( last_price ), dtos ( price ), dtos ( c_order::get_distance ( _order_type, price, last_price ) ) ) ); double gap_factor = lot_factor * ( ( distance_p - step_p ) / step_p ) * settings.gap_lot_koef; double tripple_last_lot = last_lot * settings.gap_last_order_koef; double result = last_lot * ( lot_factor + gap_factor ); return tripple_last_lot < result ? tripple_last_lot : result; } static double calc_lot_by_balance ( double min_lot, double currency_by_001_lot, double currency, int truncate_count, double market_lot_min, bool warning ) { double sum=(currency - ((NotUsedCurrency>currency)?0:NotUsedCurrency) )*(UsedCurrencyPercent/100.0); double koaf = sum / currency_by_001_lot; double result = MathFloor(koaf)*0.01; if ( CP(result,0.01) < market_lot_min) { if (warning) { log_warning( StringFormat(SRC_HANDLER_BASE_NOT_GOOD_LOT_OPEN_MIN, sum, layer_account::currency() , koaf*0.01, market_lot_min, market_lot_min)); } return market_lot_min; } return result; } static double get_base_lot ( setting_t *settings, layer_order_setting *settings_ptr, int lvl, bool warning ) { if ( !settings.is_testing && lvl != 1 ) { if (layer_order::get_min ( settings_ptr)!=NULL) return layer_order::get_min ( settings_ptr ).lot; } return settings.currency_for_001_lot == 0 ? settings.lots : calc_lot_by_balance ( settings.lots, settings.currency_for_001_lot, settings.is_testing ? settings.testing_balance : (UseBalanceForMM?kernel_account::balance():kernel_account::equity()), settings.lot_exp, settings.is_testing ? settings.testing_layer_market_lot_min : layer_market::lot_min(), warning); } static double get_by_min_order ( setting_t *settings, layer_order_setting *order_layer_settings_ptr, int lvl, enum_gap_control_type control_type, double price, double first_lot ) { #ifdef RIGAL_MOD_3 ////--- Rigal double result = settings.test_min_lot > DBL_EPSILON ? settings.test_min_lot : first_lot; ////--- #else //RIGAL_MOD_3 double result = first_lot; #endif //RIGAL_MOD_3 switch ( control_type ) { case no_gap: case op_stop: result *= get_factor ( settings, lvl ); break; case inc_lot: //result = get_for_gap_control ( settings, settings_ptr.order_type, count + 1, result, open_prices[count - 1], price ); break; } #ifdef RIGAL_MOD_3 ////--- Rigal if(settings.test_min_lot > DBL_EPSILON) result = first_lot / settings.test_min_lot * NormalizeDouble(result, settings.lot_exp); ////--- #endif //RIGAL_MOD_3 return result; } static double get_by_last_order ( setting_t *settings, layer_order_setting *settings_ptr, int lvl, enum_gap_control_type control_type, double price, double first_lot ) { #ifdef RIGAL_MOD_3 ////--- Rigal double result = settings.test_min_lot > DBL_EPSILON ? settings.test_min_lot : first_lot; ////--- #else //RIGAL_MOD_3 double result = first_lot; #endif //RIGAL_MOD_3 switch ( control_type ) { case no_gap: case op_stop: for ( int i = 1; i < lvl; i++ ) { result *= get_factor ( settings, i + 1 ); } break; case inc_lot: { int count = 0; double open_prices[]; list *orders = layer_order::get ( settings_ptr ); ArrayResize ( open_prices, orders.count ); LIST_FOREACH ( orders, c_order *, item, { count += 1; open_prices[count - 1] = item.open_price; } ); if ( count == 0 ) { break; } for ( int i = 1; i < count; i++ ) { result = get_for_gap_control ( settings, settings_ptr.order_type, i + 1, result, open_prices[i - 1], open_prices[i] ); } result = get_for_gap_control ( settings, settings_ptr.order_type, count + 1, result, open_prices[count - 1], price ); break; } } #ifdef RIGAL_MOD_3 ////--- Rigal if(settings.test_min_lot > DBL_EPSILON) result = first_lot / settings.test_min_lot * NormalizeDouble(result, settings.lot_exp); ////--- #endif //RIGAL_MOD_3 return result; } public: static double get ( setting_t *settings, layer_order_setting *settings_ptr, int lvl, enum_gap_control_type control_type, double price , bool warning) { double base_lot = get_base_lot ( settings, settings_ptr, lvl, warning ); #ifdef RIGAL_MOD_4 //--- Rigal double result = settings.test_min_lot > DBL_EPSILON ? settings.test_min_lot : base_lot; //--- #else //RIGAL_MOD_4 double result = base_lot; #endif //RIGAL_MOD_4 if ( lvl != 1 ) { result = settings.mult_type == calc_lot_type_last_order ? get_by_last_order ( settings, settings_ptr, lvl, control_type, price, result ) : get_by_min_order ( settings, settings_ptr, lvl, control_type, price, result ); } #ifdef RIGAL_MOD_4 //--- Rigal if(settings.test_min_lot > DBL_EPSILON) //--- Capteen //result = first_lot / settings.test_min_lot * NormalizeDouble(result, settings.lot_exp); result = base_lot / settings.test_min_lot * NormalizeDouble(result, settings.lot_exp); //--- #endif //RIGAL_MOD_4 if ( settings.max_lot != 0.00 ) { double max_lot = settings.max_lot * base_lot; if ( max_lot < result ) { result = max_lot; } } return result; }; }; #endif