/// <summary>
        /// Vrifico se ci sono bolle particolamente vecchie da eliminare
        /// </summary>
        private void CheckBubblesToCancel()
        {
            //recupero le vecchie bolle solo se sono in una situazione di stallo e mi mancano bolle
            if (_market.Bubbles.Count + this.WishList.Count < _configuration.MaxBubbles*(decimal) 0.8)
            {
                return;
            }

            // ne creo solo una (distruggere le bolle costa)
            foreach (CBubble bubble in _market.Bubbles)
            {
                if (bubble.SellAt > _market.Ask * BubbleDestructionLevel)
                {
                    // distruggi la bolla 
                    var marketValue = _market.Ask;
                    var orderId = "";
                    _market.DoOrder(CUtility.OrderType.Sell, marketValue, bubble.Coins, ref orderId, true);
                    CUtility.Log("*** Bubble destroyed");
                    bubble.Deleted = true;
                    _bubblesCanceled++;

                    // crea una bolla in wishlist
                    WishList.Add(CBubble.Create(_market, CUtility.OrderType.Buy, bubble.Coins, bubble.BuyAt, _configuration.Gain,orderId));

                    break;
                }
            }
            var removed = _market.Bubbles.RemoveAll(o => o.Deleted == true);
        }
 public void Log(string msg)
 {
     if (MainConfiguration.Configuration.Verbose)
     {
         CUtility.Log(msg);
     }
 }
        /// <summary>
        /// il tick è il momento in cui vengono prese le decisioni di buy/sell
        /// </summary>
        private void OnTick()
        {
            CUtility.Log("*** tick");

            // in questo simulatore se il mercato scende non ci muoviamo
            if (_trend < 0)
            {

                // verifico se ci sono bolle irraggiungibili
                if (EnableBubbleDestruction)
                {
                    CheckBubblesToCancel();
                }

                CUtility.Log("*** trend down... skip");
                return;
            }

            // analizzo il numero di bolle, per crearne almeno una
            var numBubbles = _market.Bubbles.Count() + WishList.Count();
            if (numBubbles < _configuration.MaxBubbles)
            {
                CreateBubble();
            }

            // mostro le bolle
            _market.ShowBubbles();
        }
 public void Print()
 {
     foreach (Tag t in _tags.Values)
     {
         CUtility.Log(string.Format("{0} {1} {2}", t.Label, t.Called, t.Confirmed));
     }
 }
 public void Log()
 {
     CUtility.Log(string.Format("Candle {0} {1} {2}", this.Date.ToString(CultureInfo.InvariantCulture), Math.Round(this.Close, 4).ToString(CultureInfo.InvariantCulture), this.Color.ToString()));
     //CUtility.Log("Date  : " + this.Date.ToString(CultureInfo.InvariantCulture));
     //CUtility.Log("Bid   : " + Math.Round(this.Close, 4).ToString(CultureInfo.InvariantCulture));
     //CUtility.Log("Color : " + this.Color.ToString());
     CUtility.Log("");
 }
Ejemplo n.º 6
0
 public void Print()
 {
     CUtility.Log("money     : " + Money.ToString(CultureInfo.InvariantCulture));
     CUtility.Log("coins     : " + Coins.ToString(CultureInfo.InvariantCulture));
     CUtility.Log("coinvalue : " + Coinvalue.ToString(CultureInfo.InvariantCulture));
     CUtility.Log("value     : " + Value.ToString(CultureInfo.InvariantCulture));
     CUtility.Log("i         : " + i.ToString(CultureInfo.InvariantCulture));
     CUtility.Log("j         : " + j.ToString(CultureInfo.InvariantCulture));
     CUtility.Log("w         : " + w.ToString(CultureInfo.InvariantCulture));
     CUtility.Log("k         : " + k.ToString(CultureInfo.InvariantCulture));
 }
        private void CreateBubble()
        {

            CUtility.Log("*** order buy");
            var marketValue = _market.Bid;
            string orderId = "";

            // non compro perchè il valore di mercato è circa il 10% di altre bolle presenti
            if (_market.Bubbles.Any(o => Math.Abs(o.MarketValue - marketValue) <= marketValue/10))
            {
                return;
            }


            // soldi nel wallet, ma non piu' del massimo consentito
            decimal availableMoney = _market.TotMoney;
            if (availableMoney > _configuration.MaxMoney)
            {
                availableMoney = _configuration.MaxMoney;
            }

            // come creo una bolla ? 
            var money = availableMoney / _configuration.MaxBubbles;
            var coins = money / marketValue;

            if (coins > _configuration.MaxCoinsPerBubble)
            {
                coins = _configuration.MaxCoinsPerBubble;
            }

            // verifico di non aver impiegato troppi soldi
            

            // verifico di non aver superato le soglie minime di coins e soldi

            _market.DoOrder(CUtility.OrderType.Buy, marketValue, coins, ref orderId, true);
            CUtility.Log("*** Bubble added");
            _bubblesCreated++;
            _market.Bubbles.Add(CBubble.Create(_market, CUtility.OrderType.Buy, coins, marketValue,
                _configuration.Gain, orderId));           
        }
        /// <summary>
        /// elimina le bolle che hanno raggiunto il guadagno
        /// </summary>
        private bool CheckBubbles()
        {
            if (_trend >= 0)
            {
                // se il trend è in salita aspetto (dovrebbe ottimizzare i guadagni)
                //return false;
            }

            if (_market.Bubbles.Count > 0 )
            {
                // scoppio le bolle
                foreach (CBubble bubble in _market.Bubbles)
                {
                    if (bubble.SellAt < _market.Ask)
                    {
                        //scoppio la bolla: cioè vendo i bitcoin per poterli riutilizzare
                        var marketValue = _market.Ask;
                        var orderId = "";
                        _market.DoOrder(CUtility.OrderType.Sell, marketValue, bubble.Coins, ref orderId, true);
                        CUtility.Log("*** Bubble removed");
                        _bubblesExploded++;
                        bubble.Deleted = true;

                        // occorrerebbe mettere un acquisto di btc appena sono convenienti

                    }
                }
                // rimuovo le bolle scoppiate
                var removed = _market.Bubbles.RemoveAll(o => o.Deleted == true);
                // se ho scoppiato bolle aspetto un tick
                if (removed > 0)
                {
                    _market.ShowBubbles();
                    //return;
                }
                return removed > 0;
            }
            return false;

        }
Ejemplo n.º 9
0
 public Trend SuggestedTrend()
 {
     double perc = 0;
     var prediction = Guess(out perc);
     CUtility.Log("Perc   : " + perc);
     CUtility.Log("Pattern: " + prediction.ToString().Replace("BitVector32{","").Replace("}","").Substring(28));
     if (perc > 0.33)
     {
         var numGreen = 0;
         for (var i = 0; i < Dim2;i++)
         {
             if (prediction[0])
             {
                 numGreen++;
             }
         }
         if (numGreen >= Dim2*3/4)
         {
             return Trend.Raise;
         }
         else
         {
             if (numGreen == Dim2/2)
             {
                 return Trend.Stable;
             }
             else
             {
                 return Trend.Fall;
             }
         }
         
     }
     else
     {
         return Trend.Unknown;
     }
 }
        // Specify what you want to happen when the Elapsed event is raised.
        private  void OnHeartBeat(object source, ElapsedEventArgs e)
        {
            try
            {


                // è scattato un heartbeat
                //var stop = false;
                CUtility.Log("*** heartbeat");

                // verifico lo stato del mercato
                _market.GetTicker();

                // aggiorno la mia situazione
                _market.GetWallet();

                /*
                // trend
                _trend = _market.Trend.CalculateTrend();

                // ema
                _ema = _market.Trend.Ema;

                // il trend deve essere affidabile altrimenti esce
                if (!_market.Trend.TrendIsValid)
                {
                    return;
                }
                */
                if (!_market.CandleMaker.Analyze.IsValid())
                {
                    return;
                }
                

                // elimina le bolle (ad ogni tick.. prima si fa e meglio è)
                var hasExplodedBubbles = CheckBubbles();

                // check wishlist
                var hasResolvedWishList = CheckWishList();

                if (!hasExplodedBubbles && !hasResolvedWishList)
                {
                    // strategia per il tick
                    if (_configuration.TickDynamic)
                    {
                        _ticksPerHearthBeat = NextTick(_ticksPerHearthBeat);
                    }

                    // verifico se deve scattare un tick
                    _tickCounter++;
                    if (_tickCounter >= _ticksPerHearthBeat)
                    {
                        // non uso il mod perchè potrei dover usare un 
                        // cambio dinamico al tickcounter
                        _tickCounter = 0;
                        OnTick();

                    }
                }
                // al termine dei task decido se fermare il processo oppure no

                if (_market.Stop)
                {
                    _stopwatch.Stop();
                    _heartBeatTimer.Enabled = false;
                    CUtility.Log("Time Elapsed : " + _stopwatch.Elapsed);
                }

                // secondo me questo è il momento in cui vanno salvate le persistenze
            }
            catch (Exception)
            {
                CUtility.Log("Error in hearthbeat : ");
                //throw;
            }
            finally
            {
                CUtility.Log("Created  : " + this._bubblesCreated);
                CUtility.Log("Exploded : " + this._bubblesExploded);
                CUtility.Log("Canceled : " + this._bubblesCanceled);
                CUtility.Log("Whish    : " + this.WishList.Count);
            }
        }
Ejemplo n.º 11
0
        public override void Run()
        {
            //creo il file per l'esecuzione corrente
            var filename = string.Format(@"log\{0}_{1}.txt", "Test2", DateTime.Now.ToString("ddMMyyyy_hhmm"));
            //   System.IO.File.Create(filename);


            //apro lo stream writer
            //   using (System.IO.StreamWriter sw = new System.IO.StreamWriter(@"..\..\log\mtgoxcandlesMonth-15m", true))
            {
                //lettura delle configurazioni
                var configuration = new ConfigurationHoldAndBuy()
                {
                    Gain = (decimal)0.05,      // 1%
                    //HeartBeat = (decimal)0.001, // 1m
                    MaxBubbles            = 1, //(j+1),
                    MaxCoinsPerBubble     = (decimal)(0.6),
                    MinimumCoinsPerBubble = (decimal)0.01,
                    //MaxMoney = 100,
                    //Tick = 1, //w+1,
                    //TickDynamic = false
                };

                //parametri MACD
                var arr   = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
                var param = from i in arr
                            from j in arr
                            from k in arr
                            select new { i, j, k };

                //iterazione lungo i parametri
                param.ToList().ForEach(p =>
                {
                    //generazione del market
                    var market = new CMarketSimulator(); //(15, 17, 12 + p.i, 20 + p.j, 5 + p.k);

                    //istanzio il manager
                    var manager = new Manager.CManagerHoldBuy()
                    {
                        ConfigurationHoldAndBuy = configuration,
                        Market = market
                    };//(configuration, market, true);

                    //lancio il test

                    // salvo il risultato
                    var test = new TestUnit()
                    {
                        Bubbles           = configuration.MaxBubbles,
                        Coins             = market.TotCoins,
                        Money             = market.TotMoney,
                        Gain              = configuration.Gain,
                        Maxcoinsperbubble = configuration.MaxCoinsPerBubble,
                        Coinvalue         = market.Bid,
                        //Ticks = configuration.Tick,
                        Value   = market.TotValue,
                        Average = market.Average,
                        i       = p.i,
                        j       = p.j,
                        //w=w,
                        k = p.k
                    };

                    //stampo il test
                    CUtility.Log("*** TEST");
                    //  test.PrintOnFile(sw);
                    //test.PrintOnConsole();
                    test.Print();
                });
            }
        }
Ejemplo n.º 12
0
        private decimal _lastCoin  = -1; // non si puo' usare decimal.MinValue


        public override bool OnHeartBeat()
        {
            const decimal gain = 0M; // sellat, buyat

            // devo vendere o devo comprare?
            var action = this.SuggestedAction;

            /*
             * // mi salvo il massimo value
             * if (Market.TotValue > this.MaxValue)
             * {
             *  this.MaxValue = Market.TotValue;
             * }
             *
             * if (Market.TotCoins > this.MaxCoins)
             * {
             *  this.MaxCoins = Market.TotCoins;
             * }
             */
            /**************************************************************
            *  CHECK CONFERMA (DOPPIO COMANDO)
            **************************************************************/
            // questa parte di codice esegue l'operazione se c'è una conferma
            if (action != TradeAction.StrongBuy && action != TradeAction.StrongSell)
            {
                if (action != _lastTradeActionSuggested)
                {
                    //CUtility.Log("refused: wait confirm with 2nd command");
                    LogTrade.Motivation       = "refused: wait confirm with 2nd command";
                    _lastTradeActionSuggested = action;
                    action = TradeAction.Unknown;
                }
            }
            else
            {
                LogTrade.Motivation       = ("refused: single command");
                _lastTradeActionSuggested = TradeAction.Unknown;
            }

            LogTrade.Action = action;

            /**************************************************************
            *  BUY
            **************************************************************/
            // compro o vendo?
            string orderId = "";

            if (action == TechnicalAnalysis.TradeAction.Buy || action == TechnicalAnalysis.TradeAction.StrongBuy)
            {
                /*
                 * per comprare devo usare il valore ask
                 */
                var buyvalue = Market.Buy;

                var money = (Market.TotMoney - SavedMoney) * PercCapital; // impegno solo una percentuale del capitale

                SavedMoney += (Market.TotMoney - SavedMoney) * (1 - PercCapital);

                if (money == 0)
                {
                    LogTrade.Motivation = ("refused: no money");
                    goto exitif;
                }

                if (PercCapital < 1.0M)
                {
                    // se uso una percentuale, allora devo evitare che ripetuti comandi
                    // uguali, mi facciamo dissipare il risparmio accantonato
                    if (_lastTradeActionExecuted == CUtility.OrderType.Buy)
                    {
                        goto exitif;
                    }
                }

                if (Conservative)
                {
                    // impegno sempre non più di una certa cifra
                    // sia per vendere che per comprare
                    if (money > MainConfiguration.Configuration.ManagerConservativeMaxMoneyToInvest)
                    {
                        SavedMoney += (money - MainConfiguration.Configuration.ManagerConservativeMaxMoneyToInvest);
                        money       = MainConfiguration.Configuration.ManagerConservativeMaxMoneyToInvest;
                    }
                }

                var amount = money / buyvalue; // coins
                if (amount > MinBitCoin)
                {
                    // compro solo se i coin risultanti sono più dei precedenti
                    var coins = (amount) * (1 - Market.Fee);

                    /* onlyIfGain attiva o disattiva il blocco delle vendite se i soldi ricavati sono inferiori rispetto alla vendita precedente */
                    var onlyIfGain = MainConfiguration.Configuration.GreedyWithCoins; // --> disabilità il blocco
                    var greedyPerc = MainConfiguration.Configuration.GreedyWithCoinsGain;


                    if (MainConfiguration.Configuration.GreedyWithLongTermTrend)
                    {
                        // diventa avido se il trend a lungo termine è in discesa
                        onlyIfGain = this.CurrentLongTermTrend == Trend.Fall;
                        var longTermCoefficienteAngolare = this.Market.CandleMaker.LongTermTrendSpeed();

                        greedyPerc = GreedyNess(longTermCoefficienteAngolare);
                    }

                    if (!onlyIfGain || action == TechnicalAnalysis.TradeAction.StrongBuy || coins > _lastCoin * greedyPerc)
                    {
                        // evito che il trading mi mandi sotto del numero iniziale di coins

                        if (MainConfiguration.Configuration.UndervalueAllowed || (coins + SavedCoins) > MainConfiguration.Configuration.StartWalletCoins * (1 - MainConfiguration.Configuration.UndervalueTolerance))
                        {
                            _lastCoin = coins;

                            var result = Market.DoOrder(CUtility.OrderType.Buy, buyvalue, amount, ref orderId, true);
                            if (result.Length > 0)
                            {
                                LogTrade.Motivation      = "BUY";
                                _lastTradeActionExecuted = CUtility.OrderType.Buy;
                                TotBid++;

                                // avvisa l'analitic che l'ultima label inserita con AnalyticsTools.Call(xxxx) è completata
                                AnalyticsTools.Confirm();

                                SellAt = (1 + gain) * (buyvalue * (1 + (2 * Market.Fee)));
                                BuyAt  = 0;
                            }
                            else
                            {
                                // c'è stato un fallimento
                                LogTrade.Motivation = "BUY FAILED";
                            }
                        }
                        else
                        {
                            LogTrade.Motivation = ("under my initial value");
                        }
                    }
                    else
                    {
                        LogTrade.Motivation = ("greedy of coins: waiting for better performance " + Math.Round(_lastCoin * greedyPerc, 4).ToString(CultureInfo.InvariantCulture));
                    }
                }
                // _stoploss.Reset();
            }


            /**************************************************************
            *  SELL
            **************************************************************/
            if (action == TechnicalAnalysis.TradeAction.Sell || action == TechnicalAnalysis.TradeAction.StrongSell)
            {
                var sellvalue = Market.Sell;

                var amount = (Market.TotCoins - SavedCoins) * PercCapital;// - SavedCoins;

                SavedCoins += (Market.TotCoins - SavedCoins) * (1 - PercCapital);

                if (amount == 0)
                {
                    LogTrade.Motivation = ("refused: no coins");
                    goto exitif;
                }

                if (PercCapital < 1.0M)
                {
                    // se uso una percentuale, allora devo evitare che ripetuti comandi
                    // uguali, mi facciamo dissipare il risparmio accantonato
                    if (_lastTradeActionExecuted == CUtility.OrderType.Sell)
                    {
                        goto exitif;
                    }
                }


                if (Conservative)
                {
                    // impegno sempre non più di una certa cifra
                    // sia per vendere che per comprare
                    var maxmoney = MainConfiguration.Configuration.ManagerConservativeMaxMoneyToInvest;
                    if (amount > maxmoney / sellvalue)
                    {
                        SavedCoins += (amount - maxmoney / sellvalue);
                        if (SavedCoins > 100)
                        {
                            CUtility.Log("error");
                        }
                        amount = maxmoney / sellvalue;
                    }
                }

                if (amount > MinBitCoin)
                {
                    var money = (amount * sellvalue) * (1 - Market.Fee);

                    /* onlyIfGain attiva o disattiva il blocco delle vendite se i soldi ricavati sono inferiori rispetto alla vendita precedente */
                    var onlyIfGain = MainConfiguration.Configuration.GreedyWithMoney; //  --> disabilita il blocco
                    var greedyPerc = MainConfiguration.Configuration.GreedyWithMoneyGain;

                    if (MainConfiguration.Configuration.GreedyWithLongTermTrend)
                    {
                        // diventa avido se il trend a lungo termine è in salita
                        onlyIfGain = this.CurrentLongTermTrend == Trend.Raise;
                        var longTermCoefficienteAngolare = this.Market.CandleMaker.LongTermTrendSpeed();

                        greedyPerc = GreedyNess(longTermCoefficienteAngolare);
                    }

                    if (!onlyIfGain || action == TechnicalAnalysis.TradeAction.StrongSell || money > _lastMoney * greedyPerc)
                    {
                        // evito che il trading mi butti sotto del numero iniziale di soldi
                        if (MainConfiguration.Configuration.UndervalueAllowed || (money + SavedMoney) > MainConfiguration.Configuration.StartWalletMoney * (1 - MainConfiguration.Configuration.UndervalueTolerance))
                        {
                            // vendo solo se la vendita produce piu' soldi di prima
                            _lastMoney = money;

                            var result = Market.DoOrder(CUtility.OrderType.Sell, sellvalue, amount, ref orderId, true);
                            if (result.Length > 0)
                            {
                                TotAsk++;

                                BuyAt  = (1 - gain) * (sellvalue * (1 - (2 * Market.Fee)));
                                SellAt = 0;

                                // avvisa l'analitic che l'ultima label inserita con AnalyticsTools.Call(xxxx) è completata
                                AnalyticsTools.Confirm();

                                _lastTradeActionExecuted = CUtility.OrderType.Sell;
                                LogTrade.Motivation      = "SELL";
                            }
                            else
                            {
                                LogTrade.Motivation = "SELL FAILED";
                            }

                            /*
                             * if (action == TechnicalAnalysis.TradeAction.SellStopLoss)
                             * {
                             *  TotStopLoss++;
                             * }
                             */
                        }
                        else
                        {
                            LogTrade.Motivation = ("under my initial value");
                        }
                    }
                    else
                    {
                        LogTrade.Motivation = ("greedy of money: waiting for better performance " + Math.Round(_lastMoney * greedyPerc, 4).ToString(CultureInfo.InvariantCulture));
                    }
                }
            }


exitif:

            /**************************************************************
            *  LOG
            **************************************************************/
            Log(string.Format("B:{0} A:{1} SL:{2} Max$:{3} MaxC:{4} MaxV:{5}", TotBid, TotAsk, 0, Math.Round(Market.MaxMoney, 4).ToString(CultureInfo.InvariantCulture), Math.Round(Market.MaxCoins, 4).ToString(CultureInfo.InvariantCulture), Math.Round(Market.MaxValue, 4).ToString(CultureInfo.InvariantCulture)));
            LogTrade.BuyAt  = BuyAt;
            LogTrade.SellAt = SellAt;

            return(true);
        }
        public override TradeAction SuggestedAction(CMarket market)
        {
            /********************************************************************************
            * COSTANTI (evaluator)
            ********************************************************************************/

            //var timeUnit = 15;

            //data corrente (servirebbe la data del ticker, ma vabbè...)
            var now = market.CandleMaker.GetLastCandles()[0].Date;

            var lastCandle = new
            {
                m15 = market.CandleMaker.GetLastCandles()[0],
                h1  = market.CandleMakerHourly.GetLastCandles()[0],
            };

            //valutatore
            var E = Evaluations.EvaluationManager.Instance;

            //formatta i nomi degli indicatori
            Func <string, string> N = (o =>
            {
                return(string.Format("{0}[{1}]", o, this.Name));
            });



            /********************************************************************************
            * COSTANTI
            ********************************************************************************/

            var currentTrend = market.CandleMaker.Analyze.CurrentTrend; //Trend();
            var roclimit     = MainConfiguration.Configuration.AlarmStrongSellBuyRocLimit;
            var macdlimit    = MainConfiguration.Configuration.AlarmStrongSellMacdLimit;

            /********************************************************************************
            * STOP LOSS
            ********************************************************************************/
            if (MainConfiguration.Configuration.EnableStopLoss)
            {
                if (StopLoss.IsSell(this.CoinValue))
                {
                    if (currentTrend == TechnicalAnalysis.Trend.Fall)
                    {
                        StopLoss.Reset();
                        StopLoss.SellCounter++;

                        //EVAL: se uso lo stoploss, sto prevedendo che il prezzo scenda, anche di poco
                        E.Add(N("stoploss"), CreatePrediction(now, TradeAction.StrongSell), timeUnit);
                    }
                }
            }

            if (!IsValid())
            {
                //AnalyticsTools.Call("notyetready");
                return(TradeAction.Unknown);
            }



            /********************************************************************************
            * ROC (non ancora usato)
            ********************************************************************************/
            if (true)
            {
                var rocSpeed = Roc.Derivative.CurrentSpeed;
                if (Rocdiff > roclimit && rocSpeed <= 0 && currentTrend == TechnicalAnalysis.Trend.Fall)
                {
                    //LogTrade.Note = "inversione: vendere";
                    //EVAL: se dico di vendere, vuol dire che il prezzo scenderà, anche di poco
                    E.Add(N("-(rocdiff;rocspeed)"), CreatePrediction(now, TradeAction.Sell), timeUnit);

                    if (CurrentMacdValue > macdlimit)
                    {
                        //EVAL: questo è un rafforzativo, quindi mi aspetto un grande ribasso
                        E.Add(N("++(rocdiff;rocspeed;Macd122609)"), CreatePrediction(now, TradeAction.StrongSell), timeUnit);

                        //return TradeAction.StrongSell;
                    }
                }
                if (Rocdiff < -roclimit && rocSpeed <= 0 && currentTrend == TechnicalAnalysis.Trend.Raise)
                {
                    //LogTrade.Note = "inversione: comprare";
                    //EVAL: se dico di comprare, vuol dire che il prezzo salirà, anche di poco
                    E.Add(N("+(rocdiff;rocspeed)"), CreatePrediction(now, TradeAction.Buy), timeUnit);

                    if (CurrentMacdValue < -macdlimit)
                    {
                        //EVAL: questo è un rafforzativo, quindi mi aspetto un grande rialzo
                        E.Add(N("++(rocdiff;rocspeed;Macd122609)"), CreatePrediction(now, TradeAction.StrongBuy), timeUnit);
                        // return TradeAction.StrongBuy;
                    }
                }
            }
            if (true)
            {
                // se si mette a true, questo garantisce 12k e 15btc (l'altro pezzo sul roc va messo in tuning
                if (Rocdiff > roclimit && currentTrend == TechnicalAnalysis.Trend.Fall)
                {
                    //LogTrade.Note = "inversione: vendere";
                    //EVAL: se dico di vendere, vuol dire che il prezzo scenderà, anche di poco
                    E.Add(N("-(rocdiff)"), CreatePrediction(now, TradeAction.Sell), timeUnit);

                    if (CurrentMacdValue > 2)
                    {
                        //EVAL: questo è un rafforzativo, quindi mi aspetto un grande ribasso
                        E.Add(N("--(rocdiff;Macd122609)"), CreatePrediction(now, TradeAction.StrongSell), timeUnit);
                        //return TradeAction.StrongSell;
                    }
                }
                if (Rocdiff < -roclimit && currentTrend == TechnicalAnalysis.Trend.Raise)
                {
                    //LogTrade.Note = "inversione: comprare";
                    //EVAL: se dico di comprare, vuol dire che il prezzo salirà, anche di poco
                    E.Add(N("+(rocdiff;rocspeed)"), CreatePrediction(now, TradeAction.Buy), timeUnit);

                    if (CurrentMacdValue < -2)
                    {
                        //EVAL: questo è un rafforzativo, quindi mi aspetto un grande rialzo
                        E.Add(N("++(rocdiff;rocspeed;Macd122609)"), CreatePrediction(now, TradeAction.StrongBuy), timeUnit);
                        // return TradeAction.StrongBuy;
                    }
                }

                /********************************************************************************
                * ALLARMI
                ********************************************************************************/

                var emadiffValue = EmaDiff.CurrentValue;  //EmaDiff.Calculate(); // potrebbe essere inutile (lo abbiamo già)
                var macdValue    = this.CurrentMacdValue; // potrebbe essere inutile (lo abbiamo già)
                //var roclimit = 5.0M;
                if (Math.Sign(emadiffValue) == Math.Sign(macdValue))
                {
                    var limit = MainConfiguration.Configuration.AlarmStrongSellBuyLimit; // occorre capire che valori sono i migliori


                    if ((emadiffValue < -limit && macdValue < -limit))
                    {
                        //LogTrade.Note = ("suggestion: (emadiffValue < -limit && macdValue < -limit)");
                        // AnalyticsTools.Call("ema;macd;limit;-");
                        //return TradeAction.StrongSell;

                        //EVAL:
                        E.Add(N("--(ema;macd;limit;)"), CreatePrediction(now, TradeAction.StrongSell), timeUnit);
                    }

                    if (emadiffValue > limit && macdValue > limit)
                    {
                        //LogTrade.Note = ("suggestion:  (emadiffValue > limit && macdValue > limit)");
                        // AnalyticsTools.Call("ema;macd;limit;+");
                        // return TradeAction.StrongBuy;

                        //EVAL:
                        E.Add(N("++(ema;macd;limit;)"), CreatePrediction(now, TradeAction.StrongBuy), timeUnit);
                    }

                    if (emadiffValue < -1 && macdValue < -1)
                    {
                        //LogTrade.Note = ("suggestion:  (emadiffValue < -1 && macdValue < -1)");
                        // AnalyticsTools.Call("ema;macd;-1");
                        // return TradeAction.Sell;

                        //EVAL:
                        E.Add(N("-(ema;macd;-1;)"), CreatePrediction(now, TradeAction.Sell), timeUnit);
                    }

                    if (emadiffValue > 1 && macdValue > 1)
                    {
                        //  AnalyticsTools.Call("ema;macd;+1");
                        //LogTrade.Note = ("suggestion:  (emadiffValue > 1 && macdValue > 1)");
                        //return TradeAction.Buy;

                        //EVAL:
                        E.Add(N("+(ema;macd;+1;)"), CreatePrediction(now, TradeAction.Buy), timeUnit);
                    }
                }



                var poll = new Poll();

                /********************************************************************************
                * MACD
                ********************************************************************************/
                //foreach (MacdItem item in this.MacdList)
                {
                    poll.Add(Macd122609.SuggestedAction(CurrentMacdValue, currentTrend));
                    CUtility.Log(string.Format("MACD   {0}", Math.Round(CurrentMacdValue, 4).ToString(CultureInfo.InvariantCulture)));
                }

                /********************************************************************************
                * EMADIFF
                ********************************************************************************/
                var emadiffSuggestion = EmaDiff.SuggestedAction(CurrentEmaDiff, currentTrend);
                poll.Add(emadiffSuggestion);
                CUtility.Log(string.Format("EMADIFF {0}", Math.Round(CurrentEmaDiff, 4).ToString(CultureInfo.InvariantCulture)));


                /********************************************************************************
                * DECISION
                ********************************************************************************/
                //LogTrade.Note = "poll";

                var result = poll.Result();

                if (true)
                {
                    // questo sistema di sicurezza non genera troppi problemi, ma non aumenta il reddito
                    // pero' aumenta la media dei redditi

                    // sistema di sicurezza da testare
                    const decimal securitylimit = 1.5M; // va bene cosi'


                    if (result == TradeAction.Buy && market.Buy >= securitylimit * LogTrade.BuyAt && LogTrade.BuyAt > 0 &&
                        currentTrend == TechnicalAnalysis.Trend.Raise)
                    {
                        //  AnalyticsTools.Call("expensive");
                        //  return TradeAction.Hold;

                        //EVAL: in realtà, "expensive" scommette sul fatto che può comprare a meno
                        E.Add(N("expensive"), new Evaluations.Prediction()
                        {
                            Date  = now,
                            Type  = Evaluations.PredictionType.LessThan,
                            Value = this.CoinValue * (1 - 0.01M)
                        }, timeUnit);
                    }

                    if (result == TradeAction.Sell && market.Sell <= securitylimit * LogTrade.SellAt && LogTrade.SellAt > 0 &&
                        currentTrend == TechnicalAnalysis.Trend.Fall)
                    {
                        // AnalyticsTools.Call("cheap");
                        //  return TradeAction.Hold;

                        //EVAL: in realtà, "cheap" scommette sul fatto che può vendere a più
                        E.Add(N("cheap"), new Evaluations.Prediction()
                        {
                            Date  = now,
                            Type  = Evaluations.PredictionType.GreatherThan,
                            Value = this.CoinValue * (1 + 0.01M)
                        }, timeUnit);
                    }
                }

                if (result != TradeAction.Hold)
                {
                    // AnalyticsTools.Call("poll " + result.ToString());
                }

                //return result;

                //EVAL: globale, ovvero cosa fa l'algoritmo
                // E.Add("GLOBAL", CreatePrediction(now, result), timeUnit);

                return(TradeAction.Unknown);
            }
        }
        public override void Run()
        {
            var tests = new List <TestUnit>();
            var testResultFileName = @"data\output\results" + DateTime.Now.ToString("yyyyMMddhhmmss") + ".csv";

            //TODO: caricare da configurazioni
            var testLoad = GetTestData();

            //List<TestParam> testLoad = null;

            if (testLoad == null || testLoad.Count == 0)
            {
                testLoad = new List <TestParam>()
                {
                    new TestParam(0, 0, 0, 0)
                };
            }

            var e = Evaluations.EvaluationManager.Instance;

            foreach (var testParam in testLoad)
            {
                e.Clear();

                /********************************************************************
                 * CONFIGURAZIONE
                 *******************************************************************/
                //MainConfiguration.Configuration = new Configuration(); //configuration;
                // MainConfiguration.Configuration = Configuration.BuildFromFile("global.json", "personal.json");
                MainConfiguration.Configuration = Configuration.BuildFromDirectory(@"data/configuration");
                MainConfiguration.Configuration.Init();
                Configuration.SaveToFile(MainConfiguration.Configuration, @"data/configuration/serialized.result.json");

                // chiama la configurazione
                Customize(testParam);

                /********************************************************************
                 * MANAGER
                 *******************************************************************/
                var manager = Manager.Builder.Create(MainConfiguration.Configuration.ManagerClass);

                if (manager == null)
                {
                    throw new Exception("manager not configured");
                }


                manager.Start();

                if (MainConfiguration.Configuration.RealTimeHeartBeat && testLoad.Count == 1)
                {
                    break;
                }

                System.Console.WriteLine(manager.Market.UniqueName);

                // salvo il risultato
                var test = new TestUnit()
                {
                    Coins     = manager.Market.TotCoins,
                    Money     = manager.Market.TotMoney,
                    Coinvalue = manager.Market.Buy,
                    Value     = manager.Market.TotValue,
                    Average   = manager.Market.Average,
                    MaxCoins  = manager.Market.MaxCoins,
                    MaxMoney  = manager.Market.MaxMoney,
                    MaxValue  = manager.Market.MaxValue,
                    Bids      = manager.Market.TotBids,
                    Ask       = manager.Market.TotAsks,
                    Gain      = manager.Statistics.Gain,
                    i         = testParam.I,
                    j         = testParam.J,
                    w         = testParam.W,
                    k         = testParam.K
                };


                /********************************************************************
                 * VISUALIZZAZIONE
                 *******************************************************************/
                // stampa il risultato
                test.Print();
                if (test.Average > MainConfiguration.Configuration.StartWalletMoney)
                // deve esserci stato almeno un trade
                {
                    if (test.Value > MainConfiguration.Configuration.StartWalletMoney)
                    // devo aver guadagnato piu' di quanto ho investito
                    {
                        // salva il risultato se ci sono stati risultati incoraggianti
                        CUtility.Log("*** GOOD");
                        tests.Add(test);

                        /*
                         * // scrive il risultato su csv
                         * using (var log = new StreamWriter(testResultFileName, true))
                         * {
                         *  test.Print(log);
                         *  log.Flush();
                         *  log.Close();
                         * }
                         * */
                        // scrive il risultato con codice
                        using (var log = new StreamWriter(testResultFileName + ".txt", true))
                        {
                            test.PrintCode(log);
                            log.Flush();
                            log.Close();
                        }

                        // salvo la migliore configurazione
                        var best = tests.OrderByDescending(o => o.Coins * o.Coinvalue + o.Money).FirstOrDefault();
                        if (best != null)
                        {
                            Configuration.SaveToFile(MainConfiguration.Configuration,
                                                     @"data/configuration/best.result.json");
                        }
                        var bestAvg = tests.OrderByDescending(o => o.Average).FirstOrDefault();
                        if (bestAvg != null)
                        {
                            Configuration.SaveToFile(MainConfiguration.Configuration,
                                                     @"data/configuration/bestavg.result.json");
                        }
                    }
                }

                AnalyticsTools.Print();
                e.Finalize();
            }

            /********************************************************************
             * RISULTATI
             *******************************************************************/
            if (MainConfiguration.Configuration.RealTimeHeartBeat && testLoad.Count == 1)
            {
            }
            else
            {
                // mostro la performance migliore
                CUtility.Log("*** BEST VALUE");
                var firstOrDefault = tests.OrderByDescending(o => o.Coins * o.Coinvalue + o.Money).FirstOrDefault();
                if (firstOrDefault != null)
                {
                    firstOrDefault.Print();
                }

                CUtility.Log("*** BEST AVERAGE");
                var orDefault = tests.OrderByDescending(o => o.Average).FirstOrDefault();
                if (orDefault != null)
                {
                    orDefault.Print();
                }
            }
        }