EA-Setka-2/logic/calc/calc_lot.mqh

270 lines
8.2 KiB
MQL5
Raw Permalink Normal View History

2025-05-30 14:50:44 +02:00
#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<c_order *> *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