2018-05-22 10:11:50 +02:00
using System ;
using System.Collections.Generic ;
using System.IO ;
using System.Linq ;
using System.Net ;
using System.Text ;
using Newtonsoft.Json ;
using Core.Main ;
using Core.Helper ;
using Core.Main.DataObjects.PTMagicData ;
2018-12-15 22:07:29 +01:00
namespace Core.MarketAnalyzer
{
public class BaseAnalyzer
{
public static Dictionary < string , dynamic > GetJsonFromURL ( string url , LogHelper log , string api )
{
2018-05-22 10:11:50 +02:00
Dictionary < string , dynamic > jsonObject = null ;
HttpWebRequest request = ( HttpWebRequest ) WebRequest . Create ( url ) ;
2018-12-15 22:07:29 +01:00
if ( api ! = "" )
{
2018-12-01 15:05:35 +01:00
request . Headers . Add ( "X-CMC_PRO_API_KEY" , api ) ;
}
2018-05-22 10:11:50 +02:00
request . ContentType = "application/json" ;
request . UserAgent = "PTMagic.Import" ;
2018-08-12 17:34:01 +02:00
request . KeepAlive = true ;
2018-05-22 10:11:50 +02:00
2018-12-15 22:07:29 +01:00
try
{
2018-05-22 10:11:50 +02:00
HttpWebResponse httpResponse = ( HttpWebResponse ) request . GetResponse ( ) ;
StreamReader jsonReader = new StreamReader ( httpResponse . GetResponseStream ( ) ) ;
string jsonString = jsonReader . ReadToEnd ( ) ;
jsonReader . Close ( ) ;
jsonObject = JsonConvert . DeserializeObject < Dictionary < string , dynamic > > ( jsonString ) ;
return jsonObject ;
2018-12-15 22:07:29 +01:00
}
catch ( WebException ex )
{
2018-05-22 10:11:50 +02:00
log . DoLogCritical ( ex . Message , ex ) ;
throw ex ;
2018-12-15 22:07:29 +01:00
}
catch ( Exception ex )
{
2018-05-22 10:11:50 +02:00
log . DoLogCritical ( ex . Message , ex ) ;
}
return jsonObject ;
}
2018-12-15 22:07:29 +01:00
public static Newtonsoft . Json . Linq . JObject GetSimpleJsonObjectFromURL ( string url , LogHelper log , bool swallowException )
{
2018-05-22 10:11:50 +02:00
Newtonsoft . Json . Linq . JObject jsonObject = null ;
HttpWebRequest request = ( HttpWebRequest ) WebRequest . Create ( url ) ;
request . ContentType = "application/json" ;
request . UserAgent = "PTMagic.Import" ;
2018-08-12 17:34:01 +02:00
request . KeepAlive = true ;
2018-05-22 10:11:50 +02:00
2018-12-15 22:07:29 +01:00
try
{
2018-05-22 10:11:50 +02:00
HttpWebResponse httpResponse = ( HttpWebResponse ) request . GetResponse ( ) ;
StreamReader jsonReader = new StreamReader ( httpResponse . GetResponseStream ( ) ) ;
string jsonString = jsonReader . ReadToEnd ( ) ;
jsonReader . Close ( ) ;
jsonObject = JsonConvert . DeserializeObject < Newtonsoft . Json . Linq . JObject > ( jsonString ) ;
return jsonObject ;
2018-12-15 22:07:29 +01:00
}
catch ( WebException ex )
{
if ( swallowException )
{
2018-06-06 06:00:21 +02:00
// Do nothing, as we do not want to get this logged. Only uncritical functions uses this
2018-12-15 22:07:29 +01:00
}
else
{
2018-06-06 06:00:21 +02:00
log . DoLogCritical ( "Url: " + url + " Message: " + ex . Message , ex ) ;
throw ex ;
}
2018-12-15 22:07:29 +01:00
}
catch ( Exception ex )
{
if ( swallowException )
{
2018-05-23 16:07:46 +02:00
// Do nothing, as we do not want to get this logged. Only uncritical functions uses this
2018-12-15 22:07:29 +01:00
}
else
{
2018-05-23 16:07:46 +02:00
log . DoLogCritical ( "Url: " + url + " Message: " + ex . Message , ex ) ;
throw ex ;
2018-05-22 10:11:50 +02:00
}
}
return jsonObject ;
}
2018-12-15 22:07:29 +01:00
public static List < dynamic > GetSimpleJsonListFromURL ( string url , LogHelper log )
{
2018-05-22 10:11:50 +02:00
List < dynamic > jsonObject = null ;
HttpWebRequest request = ( HttpWebRequest ) WebRequest . Create ( url ) ;
request . ContentType = "application/json" ;
request . UserAgent = "PTMagic.Import" ;
2018-08-12 17:34:01 +02:00
request . KeepAlive = true ;
2018-05-22 10:11:50 +02:00
2018-12-15 22:07:29 +01:00
try
{
2018-05-22 10:11:50 +02:00
HttpWebResponse httpResponse = ( HttpWebResponse ) request . GetResponse ( ) ;
StreamReader jsonReader = new StreamReader ( httpResponse . GetResponseStream ( ) ) ;
string jsonString = jsonReader . ReadToEnd ( ) ;
jsonReader . Close ( ) ;
jsonObject = JsonConvert . DeserializeObject < List < dynamic > > ( jsonString ) ;
return jsonObject ;
2018-12-15 22:07:29 +01:00
}
catch ( WebException ex )
{
2018-05-22 10:11:50 +02:00
log . DoLogCritical ( ex . Message , ex ) ;
throw ex ;
2018-12-15 22:07:29 +01:00
}
catch ( Exception ex )
{
2018-05-22 10:11:50 +02:00
log . DoLogCritical ( ex . Message , ex ) ;
}
return jsonObject ;
}
2018-12-15 22:07:29 +01:00
public static Newtonsoft . Json . Linq . JArray GetSimpleJsonArrayFromURL ( string url , LogHelper log )
{
2018-05-22 10:11:50 +02:00
Newtonsoft . Json . Linq . JArray jsonObject = null ;
HttpWebRequest request = ( HttpWebRequest ) WebRequest . Create ( url ) ;
request . ContentType = "application/json" ;
request . UserAgent = "PTMagic.Import" ;
2018-08-12 17:34:01 +02:00
request . KeepAlive = true ;
2018-05-22 10:11:50 +02:00
2018-12-15 22:07:29 +01:00
try
{
2018-05-22 10:11:50 +02:00
HttpWebResponse httpResponse = ( HttpWebResponse ) request . GetResponse ( ) ;
StreamReader jsonReader = new StreamReader ( httpResponse . GetResponseStream ( ) ) ;
string jsonString = jsonReader . ReadToEnd ( ) ;
jsonReader . Close ( ) ;
jsonObject = JsonConvert . DeserializeObject < Newtonsoft . Json . Linq . JArray > ( jsonString ) ;
return jsonObject ;
2018-12-15 22:07:29 +01:00
}
catch ( WebException ex )
{
2018-05-22 10:11:50 +02:00
log . DoLogCritical ( ex . Message , ex ) ;
throw ex ;
2018-12-15 22:07:29 +01:00
}
catch ( Exception ex )
{
2018-05-22 10:11:50 +02:00
log . DoLogCritical ( ex . Message , ex ) ;
}
return jsonObject ;
}
2018-12-15 22:07:29 +01:00
public static string GetLatestGitHubRelease ( LogHelper log , string defaultVersion )
{
2018-05-22 10:11:50 +02:00
string result = defaultVersion ;
2018-12-15 22:07:29 +01:00
try
{
2018-12-19 15:40:44 +01:00
string baseUrl = "https://api.github.com/repos/PTMagicians/PTMagic/releases/latest" ;
2018-05-22 10:11:50 +02:00
Newtonsoft . Json . Linq . JObject jsonObject = GetSimpleJsonObjectFromURL ( baseUrl , log , true ) ;
2018-12-15 22:07:29 +01:00
if ( jsonObject ! = null )
{
2018-05-22 10:11:50 +02:00
result = jsonObject . GetValue ( "tag_name" ) . ToString ( ) ;
}
2018-12-15 22:07:29 +01:00
}
catch ( WebException ex )
{
2018-05-22 10:11:50 +02:00
log . DoLogDebug ( "GitHub version check error: " + ex . Message ) ;
2018-12-15 22:07:29 +01:00
}
catch ( Exception ex )
{
2018-05-22 10:11:50 +02:00
log . DoLogDebug ( "GitHub version check error: " + ex . Message ) ;
}
return result ;
}
2019-02-17 05:48:49 +01:00
public static double GetMainFiatCurrencyRate ( string currency , string FreeCurrencyAPI , LogHelper log )
2018-12-15 22:07:29 +01:00
{
2018-05-22 10:11:50 +02:00
double result = 1 ;
2019-02-17 05:48:49 +01:00
string baseUrl = "http://free.currencyconverterapi.com/api/v5/convert?q=USD_" + currency + "&compact=y&apiKey=" + FreeCurrencyAPI ;
2018-05-22 10:11:50 +02:00
log . DoLogDebug ( "http://free.currencyconverterapi.com - Getting latest exchange rates..." ) ;
2018-05-23 16:07:46 +02:00
Newtonsoft . Json . Linq . JObject jsonObject = GetSimpleJsonObjectFromURL ( baseUrl , log , false ) ;
2018-12-15 22:07:29 +01:00
if ( jsonObject ! = null )
{
2018-05-22 10:11:50 +02:00
log . DoLogDebug ( "http://free.currencyconverterapi.com - Received latest exchange rates." ) ;
result = ( double ) jsonObject [ "USD_" + currency ] [ "val" ] ;
log . DoLogInfo ( "http://free.currencyconverterapi.com - Latest exchange rate for USD to " + currency + " is " + result ) ;
}
return result ;
}
2018-12-15 22:07:29 +01:00
public static Dictionary < string , MarketInfo > GetMarketInfosFromFile ( PTMagicConfiguration systemConfiguration , LogHelper log )
{
2018-05-22 10:11:50 +02:00
Dictionary < string , MarketInfo > result = new Dictionary < string , MarketInfo > ( ) ;
string marketInfoFilePath = Directory . GetCurrentDirectory ( ) + Path . DirectorySeparatorChar + Constants . PTMagicPathData + Path . DirectorySeparatorChar + Constants . PTMagicPathExchange + Path . DirectorySeparatorChar + "MarketInfo.json" ;
2018-12-15 22:07:29 +01:00
if ( File . Exists ( marketInfoFilePath ) )
{
try
{
2018-05-22 10:11:50 +02:00
result = JsonConvert . DeserializeObject < Dictionary < string , MarketInfo > > ( System . IO . File . ReadAllText ( marketInfoFilePath ) ) ;
2018-12-15 22:07:29 +01:00
}
catch ( Exception ex )
{
2018-05-22 10:11:50 +02:00
log . DoLogDebug ( ex . Message ) ;
}
}
2018-12-15 22:07:29 +01:00
if ( result = = null )
{
2018-05-22 10:11:50 +02:00
result = new Dictionary < string , MarketInfo > ( ) ;
}
return result ;
}
2018-12-15 22:07:29 +01:00
public static void SaveMarketInfosToFile ( Dictionary < string , MarketInfo > marketInfos , PTMagicConfiguration systemConfiguration , LogHelper log )
{
2018-05-22 10:11:50 +02:00
FileHelper . WriteTextToFile ( Directory . GetCurrentDirectory ( ) + Path . DirectorySeparatorChar + Constants . PTMagicPathData + Path . DirectorySeparatorChar + Constants . PTMagicPathExchange + Path . DirectorySeparatorChar , "MarketInfo.json" , JsonConvert . SerializeObject ( marketInfos ) ) ;
}
2018-12-15 22:07:29 +01:00
public static Dictionary < string , Market > GetMarketDataFromFile ( PTMagicConfiguration systemConfiguration , LogHelper log , string platform , DateTime maxDateTime , string marketCaption )
{
2018-05-22 10:11:50 +02:00
Dictionary < string , Market > result = new Dictionary < string , Market > ( ) ;
DirectoryInfo dataDirectory = new DirectoryInfo ( Directory . GetCurrentDirectory ( ) + Path . DirectorySeparatorChar + Constants . PTMagicPathData + Path . DirectorySeparatorChar + platform + Path . DirectorySeparatorChar ) ;
// Get market files older than max datetime in descending order (newest file up top)
List < FileInfo > marketFiles = dataDirectory . EnumerateFiles ( "MarketData*" )
. Select ( x = > { x . Refresh ( ) ; return x ; } )
. Where ( x = > x . LastWriteTimeUtc < = maxDateTime )
. ToArray ( ) . OrderByDescending ( f = > f . LastWriteTimeUtc ) . ToList ( ) ;
FileInfo marketFile = null ;
2018-12-15 22:07:29 +01:00
if ( marketFiles . Count > 0 )
{
2018-05-22 10:11:50 +02:00
marketFile = marketFiles . First ( ) ;
log . DoLogDebug ( platform + " - " + marketCaption + " market data loaded (" + marketFile . LastWriteTimeUtc . ToString ( ) + ")" ) ;
2018-12-15 22:07:29 +01:00
}
else
{
2018-05-22 10:11:50 +02:00
log . DoLogDebug ( platform + " - Not able to load " + marketCaption + " market data. Loading next youngest market file instead." ) ;
// Get market files younger than max datetime in ascending order (oldest file up top)
marketFiles = dataDirectory . EnumerateFiles ( "MarketData*" )
. Select ( x = > { x . Refresh ( ) ; return x ; } )
. Where ( x = > x . LastWriteTimeUtc > = maxDateTime )
. ToArray ( ) . OrderBy ( f = > f . LastWriteTimeUtc ) . ToList ( ) ;
2018-12-15 22:07:29 +01:00
if ( marketFiles . Count > 0 )
{
2018-05-22 10:11:50 +02:00
marketFile = marketFiles . First ( ) ;
log . DoLogDebug ( platform + " - " + marketCaption + " market data loaded (" + marketFile . LastWriteTimeUtc . ToString ( ) + ")" ) ;
}
}
2018-12-15 22:07:29 +01:00
try
{
2018-05-22 10:11:50 +02:00
// Get JSON object
result = JsonConvert . DeserializeObject < Dictionary < string , Market > > ( marketFile . OpenText ( ) . ReadToEnd ( ) ) ;
2018-12-15 22:07:29 +01:00
}
catch ( Exception ex )
{
2018-05-22 10:11:50 +02:00
log . DoLogCritical ( ex . Message , ex ) ;
}
return result ;
}
2018-12-15 22:07:29 +01:00
public static Dictionary < string , List < MarketTrendChange > > BuildMarketTrends ( string platform , string mainMarket , List < string > marketList , string sortBy , bool isGlobal , Dictionary < string , List < MarketTrendChange > > output , PTMagicConfiguration systemConfiguration , LogHelper log )
{
2018-05-22 10:11:50 +02:00
2018-12-15 22:07:29 +01:00
try
{
2018-05-22 10:11:50 +02:00
List < MarketTrend > marketTrends = systemConfiguration . AnalyzerSettings . MarketAnalyzer . MarketTrends . FindAll ( mt = > mt . Platform . Equals ( platform , StringComparison . InvariantCultureIgnoreCase ) ) ;
2018-12-15 22:07:29 +01:00
if ( marketTrends . Count > 0 )
{
2018-05-22 10:11:50 +02:00
Dictionary < string , Market > recentMarkets = BaseAnalyzer . GetMarketDataFromFile ( systemConfiguration , log , platform , DateTime . Now . ToUniversalTime ( ) , "Recent" ) ;
2018-12-15 22:07:29 +01:00
foreach ( MarketTrend marketTrend in marketTrends )
{
if ( platform . Equals ( "Exchange" , StringComparison . InvariantCultureIgnoreCase ) )
{
2018-05-22 10:11:50 +02:00
log . DoLogInfo ( platform + " - Building market trend changes for '" + marketTrend . Name + "' on main market '" + mainMarket + "' with " + marketList . Count . ToString ( ) + " markets..." ) ;
2018-12-15 22:07:29 +01:00
}
else
{
2018-05-22 10:11:50 +02:00
log . DoLogInfo ( platform + " - Building market trend changes for '" + marketTrend . Name + "'..." ) ;
}
Dictionary < string , Market > trendMarkets = BaseAnalyzer . GetMarketDataFromFile ( systemConfiguration , log , platform , DateTime . Now . ToUniversalTime ( ) . AddMinutes ( - marketTrend . TrendMinutes ) , marketTrend . Name ) ;
List < MarketTrendChange > marketTrendChanges = BaseAnalyzer . GetMarketTrendChanges ( platform , mainMarket , marketTrend , marketList , recentMarkets , trendMarkets , sortBy , isGlobal , systemConfiguration , log ) ;
output . Add ( marketTrend . Name , marketTrendChanges ) ;
log . DoLogInfo ( platform + " - " + marketTrendChanges . Count . ToString ( ) + " Market trend changes built for '" + marketTrend . Name + "'." ) ;
}
}
2018-12-15 22:07:29 +01:00
}
catch ( Exception ex )
{
2018-05-22 10:11:50 +02:00
log . DoLogCritical ( ex . Message , ex ) ;
}
return output ;
}
2018-12-15 22:07:29 +01:00
public static List < MarketTrendChange > GetMarketTrendChanges ( string platform , string mainMarket , MarketTrend marketTrend , List < string > marketList , Dictionary < string , Market > recentMarkets , Dictionary < string , Market > trendMarkets , string sortBy , bool isGlobal , PTMagicConfiguration systemConfiguration , LogHelper log )
{
2018-05-22 10:11:50 +02:00
List < MarketTrendChange > result = new List < MarketTrendChange > ( ) ;
var sortedMarkets = new SortedDictionary < string , Market > ( recentMarkets ) . OrderBy ( m = > m . Value . Position ) ;
2018-12-15 22:07:29 +01:00
if ( sortBy . Equals ( "Volume" ) )
{
2018-05-22 10:11:50 +02:00
sortedMarkets = new SortedDictionary < string , Market > ( recentMarkets ) . OrderByDescending ( m = > m . Value . Volume24h ) ;
}
int marketCount = 1 ;
2018-12-15 22:07:29 +01:00
foreach ( KeyValuePair < string , Market > recentMarketPair in sortedMarkets )
{
if ( marketList . Count = = 0 | | marketList . Contains ( recentMarketPair . Key ) )
{
2018-05-22 10:11:50 +02:00
bool excludeMainCurrency = systemConfiguration . AnalyzerSettings . MarketAnalyzer . ExcludeMainCurrency ;
2018-12-15 22:07:29 +01:00
if ( ! marketTrend . ExcludeMainCurrency )
{
2018-05-22 10:11:50 +02:00
excludeMainCurrency = marketTrend . ExcludeMainCurrency ;
}
2018-12-15 22:07:29 +01:00
if ( platform . Equals ( "CoinMarketCap" , StringComparison . InvariantCulture ) & & excludeMainCurrency )
{
2018-05-22 10:11:50 +02:00
// Check if this is the main currency (only for CoinMarketCap)
2018-12-15 22:07:29 +01:00
if ( recentMarketPair . Value . Symbol . Equals ( mainMarket , StringComparison . InvariantCultureIgnoreCase ) )
{
2018-05-22 10:11:50 +02:00
// If the current market is the main currency, skip it
continue ;
}
}
Market recentMarket = recentMarkets [ recentMarketPair . Key ] ;
2018-12-15 22:07:29 +01:00
if ( trendMarkets . ContainsKey ( recentMarketPair . Key ) )
{
2018-05-22 10:11:50 +02:00
List < string > ignoredMarkets = SystemHelper . ConvertTokenStringToList ( marketTrend . IgnoredMarkets , "," ) ;
2018-12-15 22:07:29 +01:00
if ( ignoredMarkets . Contains ( recentMarketPair . Value . Symbol ) )
{
2018-05-22 10:11:50 +02:00
log . DoLogDebug ( platform + " - Market trend '" + marketTrend . Name + "' for '" + recentMarketPair . Key + "' is ignored in this trend." ) ;
continue ;
}
List < string > allowedMarkets = SystemHelper . ConvertTokenStringToList ( marketTrend . AllowedMarkets , "," ) ;
2018-12-15 22:07:29 +01:00
if ( allowedMarkets . Count > 0 & & ! allowedMarkets . Contains ( recentMarketPair . Value . Symbol ) )
{
2018-05-22 10:11:50 +02:00
log . DoLogDebug ( platform + " - Market trend '" + marketTrend . Name + "' for '" + recentMarketPair . Key + "' is not allowed in this trend." ) ;
continue ;
}
Market trendMarket = trendMarkets [ recentMarketPair . Key ] ;
2018-12-15 22:07:29 +01:00
if ( trendMarket ! = null )
{
2018-05-22 10:11:50 +02:00
double recentMarketPrice = recentMarket . Price ;
double trendMarketPrice = trendMarket . Price ;
2018-12-15 22:07:29 +01:00
if ( ! platform . Equals ( "CoinMarketCap" , StringComparison . InvariantCulture ) & & marketTrend . TrendCurrency . Equals ( "Fiat" , StringComparison . InvariantCultureIgnoreCase ) )
{
if ( recentMarket . MainCurrencyPriceUSD > 0 & & trendMarket . MainCurrencyPriceUSD > 0 )
{
2018-05-22 10:11:50 +02:00
recentMarketPrice = recentMarketPrice * recentMarket . MainCurrencyPriceUSD ;
trendMarketPrice = trendMarketPrice * trendMarket . MainCurrencyPriceUSD ;
}
}
double trendMarketChange = ( recentMarketPrice - trendMarketPrice ) / trendMarketPrice * 100 ;
MarketTrendChange mtc = new MarketTrendChange ( ) ;
mtc . MarketTrendName = marketTrend . Name ;
mtc . TrendMinutes = marketTrend . TrendMinutes ;
mtc . TrendChange = trendMarketChange ;
mtc . Market = recentMarket . Name ;
mtc . LastPrice = recentMarket . Price ;
mtc . Volume24h = recentMarket . Volume24h ;
mtc . TrendDateTime = DateTime . Now ;
result . Add ( mtc ) ;
log . DoLogDebug ( platform + " - Market trend '" + marketTrend . Name + "' for '" + recentMarketPair . Key + "' (Vol. " + recentMarket . Volume24h . ToString ( "#,#0.00" ) + ") is " + trendMarketChange . ToString ( "#,#0.00" ) + "% in " + SystemHelper . GetProperDurationTime ( marketTrend . TrendMinutes * 60 ) . ToLower ( ) + "." ) ;
marketCount + + ;
}
}
}
}
2018-12-15 22:07:29 +01:00
if ( marketTrend . MaxMarkets > 0 & & isGlobal )
{
2018-05-22 10:11:50 +02:00
int maxMarkets = ( marketTrend . MaxMarkets < = result . Count ) ? marketTrend . MaxMarkets : result . Count ;
result = result . GetRange ( 0 , maxMarkets ) ;
}
return result ;
}
2018-12-15 22:07:29 +01:00
public static Dictionary < string , double > BuildGlobalMarketTrends ( Dictionary < string , List < MarketTrendChange > > globalMarketTrendChanges , PTMagicConfiguration systemConfiguration , LogHelper log )
{
2018-05-22 10:11:50 +02:00
Dictionary < string , double > result = new Dictionary < string , double > ( ) ;
List < MarketTrend > marketTrends = systemConfiguration . AnalyzerSettings . MarketAnalyzer . MarketTrends ;
2018-12-15 22:07:29 +01:00
if ( marketTrends . Count > 0 )
{
foreach ( MarketTrend marketTrend in marketTrends )
{
2018-05-22 10:11:50 +02:00
log . DoLogInfo ( "Building market trend average for '" + marketTrend . Name + "'" ) ;
2018-12-15 22:07:29 +01:00
if ( globalMarketTrendChanges . ContainsKey ( marketTrend . Name ) )
{
2018-05-22 10:11:50 +02:00
List < MarketTrendChange > marketTrendChanges = globalMarketTrendChanges [ marketTrend . Name ] ;
2018-12-15 22:07:29 +01:00
if ( marketTrendChanges ! = null & & marketTrendChanges . Count > 0 )
{
2018-05-22 10:11:50 +02:00
double averageTrendChange = marketTrendChanges . Average ( mtc = > mtc . TrendChange ) ;
result . Add ( marketTrend . Name , averageTrendChange ) ;
log . DoLogInfo ( "Built average market trend change '" + marketTrend . Name + "' (" + averageTrendChange . ToString ( "#,#0.00" ) + "% in " + marketTrend . TrendMinutes . ToString ( ) + " minutes) for " + marketTrendChanges . Count . ToString ( ) + " markets." ) ;
2018-12-15 22:07:29 +01:00
}
else
{
2018-05-22 10:11:50 +02:00
result . Add ( marketTrend . Name , 0 ) ;
log . DoLogWarn ( "No market trend changes found for '" + marketTrend . Name + "' - returning 0%" ) ;
}
2018-12-15 22:07:29 +01:00
}
else
{
2018-05-22 10:11:50 +02:00
result . Add ( marketTrend . Name , 0 ) ;
log . DoLogWarn ( "Market trend '" + marketTrend . Name + "' not found in globalMarketTrendChanges[] - returning 0%" ) ;
}
}
}
return result ;
}
}
}