В С#.NET. Этот блок if/else if работает нормально, но его становится неудобно поддерживать и читать. Мне нужен более оптимизированный стиль письма.
if (Globals.SRSI < 10 && Globals.SRSI != 0 && Globals.ATR14 != 0) //Low Stochastic Entry Long Strategy
{
dStochRSIPriceLong = markPrice - (0.1 * Globals.ATR14);
ECStrategy = "Stochastic Long";
}
else if (Globals.RSI < 20 && Globals.RSI != 0 && Globals.ATR14 != 0) //RSI Rebound Long Strategy
{
dRSIPriceLong = markPrice - (0.2 * Globals.ATR14);
ECStrategy = "Rebound Long";
}
else if (Globals.MACDLINEPrevious < Globals.MACDSigLINEPrevious && Globals.MACDLINE > Globals.MACDSigLINE) //MACD Crossover Long Strategy
{
dMACDCrossoverLong = markPrice - (0.2 * Globals.ATR14);
ECStrategy = "Crossover Long";
}
else if (Math.Abs(markPrice - Globals.SMA25) > 300 && Globals.PreviousCandleLo > Globals.SMA25 && markPrice > Globals.SMA25 && Globals.SMA25 > Globals.SMA50 && Globals.SMA50 > Globals.SMA100) //Runaway Long Strategy
{
dLoCandleLong = Globals.PreviousCandleLo;
ECStrategy = "Runaway Long";
}
else if (markPrice > Globals.SMA25 && Globals.SMA25 > Globals.SMA50 && Globals.SMA50 > Globals.SMA100) //Knife Long Strategy
{
dMA2PriceLong = Globals.SMA25;
ECStrategy = "Knife Long";
}
else if (markPrice > Globals.SMA50 && Globals.SMA50 > Globals.SMA100) //Moving Average Momentum Long Strategy
{
dMAPriceLong = Globals.SMA50;
ECStrategy = "Momentum Long";
}
else if (markPrice > Globals.SMA100) //MA100 Breakout Long Strategy
{
dPullbacksPriceLong = Globals.SMA100;
ECStrategy = "Breakout Long";
}
dPositionEntryPriceLong = SearchArray(markPrice, new List<double> { dStochRSIPriceLong, dRSIPriceLong, dMACDCrossoverLong, dLoCandleLong, dMA2PriceLong, dMAPriceLong, dPullbacksPriceLong });
Очевидно, что еще будет if/else, но я надеюсь, что этого повторения не будет. Я пытался использовать список с индексом, но запутался во всей этой сложности, потому что не знаю, как составить список условий и действий, а затем найти их.
🤔 А знаете ли вы, что...
C# предоставляет средства для сериализации и десериализации данных.
Я бы предложил создать класс для каждой «стратегии»; циклический просмотр списка всех стратегий; и позволить каждому определить, применимо ли оно, и, если да, внести свой результат в список результатов. Затем интерпретируйте список или утвердите его размер 1.
interface IStrategy{
bool IsApplicable(Globals globals);
Result result(Globals globals);
}
class StochasticLongStrategy: IStrategy{
bool IsApplicable(Globals globals){
return Globals.SRSI < 10 && Globals.SRSI != 0 && Globals.ATR14 != 0;
}
Result result(Globals globals){
return Result(.....)
}
}
List<IStrategy> strategies = {new StochasticLongStrategy(),..........}
List<Result> strategyResults = new();
foreach (IStrategy strategy in strategies) {
if (strategy.IsApplicable(globals)) strategyResults.Add(strategy.Result(globals))
}
......interpret strategyResults here
Вы можете следовать этому шаблону, чтобы отделить свои «правила» от логического потока приложения.
Я не переписывал весь ваш код, потому что если вы используете этот подход, чтобы сделать свой код более выразительным и читабельным, то то, как вы называете функции, действительно важно.
// strategies / functions / rules
Func<bool> lowStoEntryLongStrat = () => Globals.SRSI < 10 && Globals.SRSI != 0 && Globals.ATR14 != 0;
Func<bool> rsiREboundLongStrat = () => Globals.RSI < 20 && Globals.RSI != 0 && Globals.ATR14 != 0;
// procedure
if (lowStoEntryLongStrat()) //Low Stochastic Entry Long Strategy
{
dStochRSIPriceLong = markPrice - (0.1 * Globals.ATR14);
ECStrategy = "Stochastic Long";
}
else if (rsiREboundLongStrat()) //RSI Rebound Long Strategy
{
dRSIPriceLong = markPrice - (0.2 * Globals.ATR14);
ECStrategy = "Rebound Long";
}
// ...
Вам также следует рассмотреть возможность использования F# или других функциональных языков для хранения формул и вычислений в более удобном для чтения виде.
Вы можете использовать список условий и соответствующих действий, чтобы сделать этот блок операторов if/else более структурированным, сжатым и простым в обслуживании. Этого можно добиться, создав список кортежей или собственный класс для хранения условия и действия, а затем пройдя по этому списку. Вот один из способов сделать это, используя собственный класс:
public class Strategy
{
public Func<bool> Condition { get; set; }
public Action Action { get; set; }
}
public void DetermineStrategy(double markPrice)
{
double dStochRSIPriceLong = 0, dRSIPriceLong = 0, dMACDCrossoverLong = 0;
double dLoCandleLong = 0, dMA2PriceLong = 0, dMAPriceLong = 0, dPullbacksPriceLong = 0;
string ECStrategy = string.Empty;
var strategies = new List<Strategy>
{
new Strategy
{
Condition = () => Globals.SRSI < 10 && Globals.SRSI != 0 && Globals.ATR14 != 0,
Action = () => { dStochRSIPriceLong = markPrice - (0.1 * Globals.ATR14); ECStrategy = "Stochastic Long"; }
},
new Strategy
{
Condition = () => Globals.RSI < 20 && Globals.RSI != 0 && Globals.ATR14 != 0,
Action = () => { dRSIPriceLong = markPrice - (0.2 * Globals.ATR14); ECStrategy = "Rebound Long"; }
},
new Strategy
{
Condition = () => Globals.MACDLINEPrevious < Globals.MACDSigLINEPrevious && Globals.MACDLINE > Globals.MACDSigLINE,
Action = () => { dMACDCrossoverLong = markPrice - (0.2 * Globals.ATR14); ECStrategy = "Crossover Long"; }
},
new Strategy
{
Condition = () => Math.Abs(markPrice - Globals.SMA25) > 300 && Globals.PreviousCandleLo > Globals.SMA25 && markPrice > Globals.SMA25 && Globals.SMA25 > Globals.SMA50 && Globals.SMA50 > Globals.SMA100,
Action = () => { dLoCandleLong = Globals.PreviousCandleLo; ECStrategy = "Runaway Long"; }
},
new Strategy
{
Condition = () => markPrice > Globals.SMA25 && Globals.SMA25 > Globals.SMA50 && Globals.SMA50 > Globals.SMA100,
Action = () => { dMA2PriceLong = Globals.SMA25; ECStrategy = "Knife Long"; }
},
new Strategy
{
Condition = () => markPrice > Globals.SMA50 && Globals.SMA50 > Globals.SMA100,
Action = () => { dMAPriceLong = Globals.SMA50; ECStrategy = "Momentum Long"; }
},
new Strategy
{
Condition = () => markPrice > Globals.SMA100,
Action = () => { dPullbacksPriceLong = Globals.SMA100; ECStrategy = "Breakout Long"; }
}
};
foreach (var strategy in strategies)
{
if (strategy.Condition())
{
strategy.Action();
break;
}
}
dPositionEntryPriceLong = SearchArray(markPrice, new List<double> { dStochRSIPriceLong, dRSIPriceLong, dMACDCrossoverLong, dLoCandleLong, dMA2PriceLong, dMAPriceLong, dPullbacksPriceLong });
}
Такой подход упрощает обслуживание и чтение условий и действий. Вы можете добавлять, удалять или изменять стратегии, не меняя структуру метода DefinStrategy.