├── Certificates ├── BuffettCodeTest.pfx └── AAACertificateServices.crt ├── BuffettCodeExcelAddin32Installer ├── Resources │ └── Icon.ico ├── LocationJp.wxl └── Bundle.wxs ├── BuffettCodeCommon ├── packages.config ├── Config │ ├── SupportedTier.cs │ ├── DataTypeConfig.cs │ ├── TabularOutputConfig.cs │ ├── ApiRequestParamConfig.cs │ ├── BuffettCodeRegistryConfig.cs │ ├── PeriodRegularExpressionConfig.cs │ └── BuffettCodeApiConfig.cs ├── Period │ ├── Snapshot.cs │ ├── IIntent.cs │ ├── LatestDayPeriod.cs │ └── ComparablePeriodUtil.cs ├── BuffettCodeAddinCache.cs ├── Exception │ ├── NotSupportedTierException.cs │ ├── NonSupportedApiVersionException.cs │ ├── NotSupportedCSVOutputDestinationException.cs │ ├── BaseBuffettCodeException.cs │ ├── UDFObsoletedFunctionCallException.cs │ ├── ApiResponseParserException.cs │ ├── PropertyNotFoundException.cs │ ├── NotSupportedDataTypeException.cs │ ├── AddinConfigurationException.cs │ └── ValidationError.cs ├── Validator │ ├── ApiFyParameterValidator.cs │ ├── CSVOutputEncodingValidator.cs │ ├── ApiFqParameterValidator.cs │ ├── MonthValidator.cs │ ├── ApiKeyValidator.cs │ ├── FiscalYearValidator.cs │ ├── FiscalQuarterValidator.cs │ └── TickerValidator.cs ├── BuffettCodeExceptionFinder.cs └── Properties │ └── AssemblyInfo.cs ├── BuffettCodeExcelFunctions ├── ITickerIntentBuilder.cs ├── packages.config ├── BCodeUdfIntentValidator.cs ├── BCodeExecutor.cs ├── DataTypeResolver.cs ├── ApiResourceFetcher.cs ├── app.config ├── BuffettCodeExcelFunctions-AddIn.dna ├── PropertyNameResolver.cs ├── PropertySelector.cs ├── Properties │ └── AssemblyInfo.cs └── TickerIntentBuilder.cs ├── InstallerCA ├── CustomAction.config ├── WindowWrapper.cs ├── ClosePromptForm.cs ├── InstallerClass.Designer.cs └── Properties │ └── AssemblyInfo.cs ├── README.md ├── BuffettCodeAPIClient ├── packages.config ├── IApiClientCore.cs ├── ApiGetResponseBodyParser.cs ├── CacheKeyCreator.cs ├── app.config ├── IBuffettCodeApiClient.cs ├── ApiGetRequest.cs ├── IIntentParameter.cs ├── ApiGetResponseValidator.cs ├── ApiRequestLock.cs ├── ApiRequestCacheHelper.cs ├── ApiClientFactory.cs ├── Properties │ └── AssemblyInfo.cs ├── BuffettCodeApiV3RequestCreator.cs ├── TickerEmptyIntentParameter.cs ├── ApiClientCoreWithCache.cs └── TickerPeriodRangeParameter.cs ├── scripts ├── sign_installer_for_build.ps1 ├── setup_code_signing_certificate.ps1 ├── sign_installer_for_release.ps1 ├── run_all_tests.ps1 ├── install_dependencies.ps1 └── upload_new_installer.ps1 ├── BuffettCodeAddinRibbonTests ├── packages.config ├── CsvDownload │ ├── CsvDownloadFormValidatorTests.cs │ ├── ApiResourceGetterTests.cs │ └── TabularWriterBuilderTests.cs ├── app.config ├── Settings │ └── CsvDownloadDefaultParametersHandlerTests.cs └── Properties │ └── AssemblyInfo.cs ├── BuffettCodeExcelFunctionsTest ├── packages.config ├── Properties │ └── AssemblyInfo.cs └── app.config ├── BuffettCodeExcelFunctionsTests ├── packages.config ├── PropertyNameResolverTests.cs ├── app.config ├── Properties │ └── AssemblyInfo.cs ├── BCodeUdfIntentParameterValidatorTests.cs └── DataTypeResolverTests.cs ├── BuffettCodeIO ├── TabularOutput │ ├── ITabularWriter.cs │ ├── TabularFormatter.cs │ ├── FormattedValueSelector.cs │ ├── TabularRow.cs │ ├── CsvFileTabularWriter.cs │ ├── Tabular.cs │ └── WorksheetTabularWriter.cs ├── Parser │ ├── ValueNormalizer.cs │ ├── IApiResponseParser.cs │ ├── ApiResponseParserFactory.cs │ ├── FixedTierRangeParser.cs │ ├── PropertyNames.cs │ └── PropertiesParser.cs ├── Property │ ├── IApiResource.cs │ ├── EmptyResource.cs │ ├── SupportedPeriodRange.cs │ ├── FixedTierRange.cs │ ├── Daily.cs │ ├── Monthly.cs │ ├── PropertyDescriptionDictionary.cs │ ├── PropertyDictionary.cs │ └── PropertyDescription.cs ├── packages.config ├── Formatter │ ├── InactionFormatter.cs │ ├── IPropertyFormatter.cs │ ├── MillionYenFormatter.cs │ ├── PropertyFormatterFactory.cs │ ├── NumericFormatter.cs │ ├── RatioFormatter.cs │ └── FormatterFactory.cs ├── Properties │ └── AssemblyInfo.cs └── app.config ├── SetupAddinRibbon32 ├── ProductProperties.wxl ├── CleanupOnUninstall.wxs ├── ModRegistriesForAddin.wxs └── Product.wxs ├── BuffettCodeCommonTests ├── packages.config ├── Validator │ ├── ApiKeyValidatorTests.cs │ ├── CSVOutputEncodingValidatorTests.cs │ ├── FiscalQuarterValidatorTests.cs │ ├── ApiFyParameterValidatorTests.cs │ ├── JpTickerValidatorTests.cs │ ├── FiscalYearValidatorTests.cs │ └── ApiFqParameterValidatorTests.cs ├── BuffettCodeExceptionFinderTests.cs ├── Properties │ └── AssemblyInfo.cs └── Period │ └── ComparablePeriodUtilTests.cs ├── BuffettCodeAddinRibbon ├── ThisAddIn.cs ├── packages.config ├── Settings │ ├── CsvDownloadOutputSettings.cs │ ├── CsvDownloadParameters.cs │ ├── CsvDownloadDefaultParametersHandler.cs │ └── AddinSettings.cs ├── Properties │ ├── Settings.settings │ └── AssemblyInfo.cs ├── ThisAddIn.Designer.xml ├── CsvDownload │ ├── CsvDownloadFormValidator.cs │ ├── ApiResourceGetter.cs │ └── CsvDownloadExceptionHandler.cs └── Ribbon.cs ├── BuffettCodeIOTests ├── packages.config ├── Parser │ ├── ApiResponseParserFactoryTests.cs │ ├── ValueNormalizerTests.cs │ ├── PropertiesParserTests.cs │ └── ColumnDescriptionParserTests.cs ├── Formatter │ ├── MillionYenFormatterTests.cs │ ├── NumericFormatterTests.cs │ └── PropertyFormatterFactoryTests.cs ├── Property │ ├── SupportedTierRangeTests.cs │ ├── PropertyDictionaryTests.cs │ ├── PropertyDescriptionDictionaryTests.cs │ └── PropertyDescriptionTests.cs ├── app.config ├── Properties │ └── AssemblyInfo.cs └── TabularOutput │ ├── TabularRowTests.cs │ └── FormattedValueSelectorTests.cs ├── BuffettCodeAPIClientTests ├── packages.config ├── app.config ├── CacheKeyCreatorTests.cs ├── ErrorMockApiClientCore.cs ├── ApiGetResponseValidatorTests.cs ├── MockApiClientCore.cs ├── ApiClientFactoryTest.cs ├── ApiGetResponseReaderTests.cs ├── ApiClientTestHelper.cs ├── PeriodRangeParameterTests.cs ├── ApiRequestCacheHelperTests.cs ├── Properties │ └── AssemblyInfo.cs ├── ApiClientCoreTests.cs ├── TickerYearMonthParameterTests.cs └── ApiClientCoreWithCacheTests.cs ├── SetupExcelFunctions32 ├── CleanupOnUninstall.wxs └── ProductProperties.wxl ├── docs ├── overview.md ├── ci_settings.md └── setup_windows_env.md └── .github └── workflows ├── lint.yml └── build.yml /Certificates/BuffettCodeTest.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BuffettCode/buffett-code-api-client-excel/HEAD/Certificates/BuffettCodeTest.pfx -------------------------------------------------------------------------------- /BuffettCodeExcelAddin32Installer/Resources/Icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BuffettCode/buffett-code-api-client-excel/HEAD/BuffettCodeExcelAddin32Installer/Resources/Icon.ico -------------------------------------------------------------------------------- /BuffettCodeCommon/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /BuffettCodeCommon/Config/SupportedTier.cs: -------------------------------------------------------------------------------- 1 | namespace BuffettCodeCommon.Config 2 | { 3 | public enum SupportedTier 4 | { 5 | None, 6 | FixedTier, 7 | OndemandTier, 8 | } 9 | } -------------------------------------------------------------------------------- /BuffettCodeExcelFunctions/ITickerIntentBuilder.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeAPIClient; 2 | 3 | namespace BuffettCodeExcelFunctions 4 | { 5 | interface ITickerIntentBuilder 6 | { 7 | ITickerIntentParameter Build(); 8 | } 9 | } -------------------------------------------------------------------------------- /InstallerCA/CustomAction.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # バフェットコード Excelアドイン 2 | このリポジトリは歴史的役割を終えたのでアーカイブされました。 3 | 今後も、バフェットコード Excelアドインは[バフェットコード](https://www.buffett-code.com/) の社内で開発を継続していきます。 4 | 5 | 6 | ## コンタクト 7 | お問い合わせは[こちら](https://www.buffett-code.com/contacts)からお願いいたします 8 | 9 | -------------------------------------------------------------------------------- /BuffettCodeAPIClient/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /scripts/sign_installer_for_build.ps1: -------------------------------------------------------------------------------- 1 | Param([string] $CertificatePath, $InstallerPath) 2 | $env:Path += ";C:\Program Files (x86)\Microsoft SDKs\ClickOnce\SignTool" 3 | 4 | Signtool sign /debug /f $CertificatePath /t http://timestamp.comodoca.com/authenticode /v $InstallerPath -------------------------------------------------------------------------------- /BuffettCodeAddinRibbonTests/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /BuffettCodeExcelFunctionsTest/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /BuffettCodeExcelFunctionsTests/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /BuffettCodeExcelFunctions/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /BuffettCodeIO/TabularOutput/ITabularWriter.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeIO.Property; 2 | using System; 3 | 4 | namespace BuffettCodeIO.TabularOutput 5 | { 6 | public interface ITabularWriter : IDisposable where T : IApiResource 7 | { 8 | void Write(Tabular tabular); 9 | } 10 | } -------------------------------------------------------------------------------- /BuffettCodeCommon/Config/DataTypeConfig.cs: -------------------------------------------------------------------------------- 1 | namespace BuffettCodeCommon.Config 2 | { 3 | // to use type => client.func 4 | public enum DataTypeConfig 5 | { 6 | Quarter, 7 | Daily, 8 | Monthly, 9 | Company, 10 | // only v2 (deprecated) 11 | Indicator, 12 | } 13 | } -------------------------------------------------------------------------------- /scripts/setup_code_signing_certificate.ps1: -------------------------------------------------------------------------------- 1 | Param([string] $S3Uri, $CertificatePath, $Pass) 2 | echo "Download an code sigining certificate to $CertificatePath from s3" 3 | aws s3 cp "$S3Uri" "$CertificatePath" --quiet 4 | echo "Import the certificate::$CertificatePath" 5 | CertUtil -user -f -p "$Pass" -importpfx "$CertificatePath" NoRoot 6 | -------------------------------------------------------------------------------- /scripts/sign_installer_for_release.ps1: -------------------------------------------------------------------------------- 1 | Param([string] $CertificatePath, $Pass, $RootCaPath, $InstallerPath) 2 | $env:Path += ";C:\Program Files (x86)\Microsoft SDKs\ClickOnce\SignTool" 3 | 4 | Signtool sign /f $CertificatePath /p $Pass /ac $RootCaPath /t http://timestamp.comodoca.com/authenticode /v $InstallerPath 5 | Signtool verify /pa $InstallerPath -------------------------------------------------------------------------------- /BuffettCodeAPIClient/IApiClientCore.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace BuffettCodeAPIClient 4 | { 5 | public interface IApiClientCore 6 | { 7 | Task Get(ApiGetRequest request, bool isConfigureAwait); 8 | 9 | IApiClientCore SetApiKey(string apiKey); 10 | string GetApiKey(); 11 | 12 | } 13 | } -------------------------------------------------------------------------------- /SetupAddinRibbon32/ProductProperties.wxl: -------------------------------------------------------------------------------- 1 | 2 | 3 | BuffettCode 4 | BuffettCodeExcelAddinRibbon 5 | 1033 6 | 7 | -------------------------------------------------------------------------------- /BuffettCodeCommonTests/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /BuffettCodeExcelAddin32Installer/LocationJp.wxl: -------------------------------------------------------------------------------- 1 | 2 | 3 | バフェットコード Excelアドイン 4 | Copyright (C) 2021 Buffett Code Inc. All rights reserved 5 | 6 | -------------------------------------------------------------------------------- /BuffettCodeAddinRibbon/ThisAddIn.cs: -------------------------------------------------------------------------------- 1 | namespace BuffettCodeAddinRibbon 2 | { 3 | public partial class ThisAddIn 4 | { 5 | private void ThisAddIn_Startup(object sender, System.EventArgs e) 6 | { 7 | } 8 | 9 | private void ThisAddIn_Shutdown(object sender, System.EventArgs e) 10 | { 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /BuffettCodeCommon/Period/Snapshot.cs: -------------------------------------------------------------------------------- 1 | namespace BuffettCodeCommon.Period 2 | { 3 | public class Snapshot : IIntent 4 | { 5 | private static readonly Snapshot instance = new Snapshot(); 6 | private Snapshot() { } 7 | 8 | public static Snapshot GetInstance() => instance; 9 | 10 | public override string ToString() => "Snapshot"; 11 | } 12 | } -------------------------------------------------------------------------------- /BuffettCodeCommon/BuffettCodeAddinCache.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.Caching; 2 | 3 | 4 | namespace BuffettCodeCommon 5 | { 6 | static public class BuffettCodeAddinCache 7 | { 8 | private static readonly MemoryCache cache = new MemoryCache("BuffettCodeExcelAddin"); 9 | 10 | public static MemoryCache GetInstance() => cache; 11 | public static void Dispose() => cache.Dispose(); 12 | } 13 | } -------------------------------------------------------------------------------- /BuffettCodeIOTests/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /BuffettCodeAPIClientTests/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /BuffettCodeIO/Parser/ValueNormalizer.cs: -------------------------------------------------------------------------------- 1 | namespace BuffettCodeIO.Parser 2 | { 3 | public static class ValueNormalizer 4 | { 5 | public static string Normalize(string value) 6 | { 7 | switch (value) 8 | { 9 | case null: return ""; 10 | case "None": return ""; 11 | default: return value; 12 | 13 | } 14 | 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /BuffettCodeAPIClient/ApiGetResponseBodyParser.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json.Linq; 2 | 3 | namespace BuffettCodeAPIClient 4 | { 5 | 6 | public class ApiGetResponseBodyParser 7 | { 8 | public static JObject Parse(string contentString) 9 | { 10 | var jObject = JObject.Parse(contentString); 11 | ApiGetResponseValidator.Validate(jObject); 12 | return jObject; 13 | } 14 | 15 | } 16 | } -------------------------------------------------------------------------------- /BuffettCodeIO/Parser/IApiResponseParser.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Config; 2 | using BuffettCodeIO.Property; 3 | using Newtonsoft.Json.Linq; 4 | using System.Collections.Generic; 5 | 6 | namespace BuffettCodeIO.Parser 7 | { 8 | public interface IApiResponseParser 9 | { 10 | IApiResource Parse(DataTypeConfig dataType, JObject json); 11 | IList ParseRange(DataTypeConfig dataType, JObject json); 12 | } 13 | } -------------------------------------------------------------------------------- /BuffettCodeIO/Property/IApiResource.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Period; 2 | using System.Collections.Generic; 3 | namespace BuffettCodeIO.Property 4 | { 5 | public interface IApiResource 6 | { 7 | string GetValue(string propertyName); 8 | 9 | PropertyDescription GetDescription(string propertyName); 10 | 11 | ICollection GetPropertyNames(); 12 | 13 | IIntent GetPeriod(); 14 | 15 | } 16 | 17 | } -------------------------------------------------------------------------------- /InstallerCA/WindowWrapper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | 4 | namespace InstallerCA 5 | { 6 | public class WindowWrapper : IWin32Window 7 | { 8 | public WindowWrapper(IntPtr handle) 9 | { 10 | _hwnd = handle; 11 | } 12 | 13 | public IntPtr Handle 14 | { 15 | get { return _hwnd; } 16 | } 17 | 18 | private readonly IntPtr _hwnd; 19 | } 20 | } -------------------------------------------------------------------------------- /BuffettCodeCommon/Period/IIntent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | 4 | namespace BuffettCodeCommon.Period 5 | { 6 | public interface IIntent 7 | { 8 | } 9 | public interface IComparablePeriod : IIntent, IComparable 10 | { 11 | IComparablePeriod Next(); 12 | } 13 | public interface IQuarterlyPeriod : IIntent { } 14 | public interface IDailyPeriod : IIntent { } 15 | public interface IYearMonthPeriod : IIntent { } 16 | } -------------------------------------------------------------------------------- /BuffettCodeCommon/Exception/NotSupportedTierException.cs: -------------------------------------------------------------------------------- 1 | namespace BuffettCodeCommon.Exception 2 | { 3 | using System; 4 | public class NotSupportedTierException : BaseBuffettCodeException 5 | { 6 | public NotSupportedTierException() : base() { } 7 | 8 | public NotSupportedTierException(string message) : base(message) { } 9 | 10 | public NotSupportedTierException(string message, Exception inner) : base(message, inner) { } 11 | } 12 | } -------------------------------------------------------------------------------- /BuffettCodeCommon/Exception/NonSupportedApiVersionException.cs: -------------------------------------------------------------------------------- 1 | namespace BuffettCodeCommon.Exception 2 | { 3 | using System; 4 | public class NonSupportedApiVersionException : BaseBuffettCodeException 5 | { 6 | public NonSupportedApiVersionException() { } 7 | public NonSupportedApiVersionException(string message) : base(message) { } 8 | public NonSupportedApiVersionException(string message, Exception inner) : base(message, inner) { } 9 | } 10 | } -------------------------------------------------------------------------------- /BuffettCodeIOTests/Parser/ApiResponseParserFactoryTests.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Config; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | namespace BuffettCodeIO.Parser.Tests 5 | { 6 | [TestClass()] 7 | public class ApiResponseParserFactoryTests 8 | { 9 | [TestMethod()] 10 | public void CreateTest() 11 | { 12 | Assert.IsInstanceOfType(ApiResponseParserFactory.Create(BuffettCodeApiVersion.Version3), typeof(ApiV3ResponseParser)); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /InstallerCA/ClosePromptForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | 4 | namespace InstallerCA 5 | { 6 | public partial class ClosePromptForm : Form 7 | { 8 | public ClosePromptForm(string text) 9 | { 10 | InitializeComponent(); 11 | messageText.Text = text; 12 | } 13 | 14 | private void OkButtonClick(object sender, EventArgs e) 15 | { 16 | DialogResult = DialogResult.OK; 17 | Close(); 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /BuffettCodeCommon/Exception/NotSupportedCSVOutputDestinationException.cs: -------------------------------------------------------------------------------- 1 | namespace BuffettCodeCommon.Exception 2 | { 3 | using System; 4 | public class NotSupportedCSVOutputDestinationException : BaseBuffettCodeException 5 | { 6 | public NotSupportedCSVOutputDestinationException() { } 7 | public NotSupportedCSVOutputDestinationException(string message) : base(message) { } 8 | public NotSupportedCSVOutputDestinationException(string message, Exception inner) : base(message, inner) { } 9 | 10 | } 11 | } -------------------------------------------------------------------------------- /BuffettCodeIOTests/Parser/ValueNormalizerTests.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.TestTools.UnitTesting; 2 | namespace BuffettCodeIO.Parser.Tests 3 | { 4 | [TestClass()] 5 | public class ValueNormalizerTests 6 | { 7 | [TestMethod()] 8 | public void NormalizeTest() 9 | { 10 | Assert.AreEqual("", ValueNormalizer.Normalize(null)); 11 | Assert.AreEqual("", ValueNormalizer.Normalize("None")); 12 | Assert.AreEqual("dummy", ValueNormalizer.Normalize("dummy")); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /BuffettCodeIO/TabularOutput/TabularFormatter.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeIO.Property; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace BuffettCodeIO.TabularOutput 6 | 7 | { 8 | public static class TabularFormatter where T : IApiResource 9 | { 10 | public static Tabular Format(IEnumerable apiResources) 11 | { 12 | var csvOutput = new Tabular(); 13 | apiResources.ToList().ForEach(r => csvOutput.Add(r)); 14 | return csvOutput; 15 | } 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /BuffettCodeCommon/Exception/BaseBuffettCodeException.cs: -------------------------------------------------------------------------------- 1 | namespace BuffettCodeCommon.Exception 2 | { 3 | using System; 4 | public abstract class BaseBuffettCodeException : Exception 5 | { 6 | public BaseBuffettCodeException() : base() 7 | { 8 | } 9 | 10 | 11 | public BaseBuffettCodeException(string message) : base(message) 12 | { 13 | } 14 | 15 | public BaseBuffettCodeException(string message, Exception inner) : base(message, inner) 16 | { 17 | 18 | } 19 | 20 | 21 | } 22 | } -------------------------------------------------------------------------------- /BuffettCodeCommon/Exception/UDFObsoletedFunctionCallException.cs: -------------------------------------------------------------------------------- 1 | namespace BuffettCodeCommon.Exception 2 | { 3 | using System; 4 | 5 | public class UDFObsoletedFunctionCallException : BaseBuffettCodeException 6 | { 7 | public UDFObsoletedFunctionCallException() : base() 8 | { 9 | } 10 | 11 | public UDFObsoletedFunctionCallException(string message) : base(message) { } 12 | 13 | 14 | public UDFObsoletedFunctionCallException(string message, Exception inner) : base(message, inner) { } 15 | 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /BuffettCodeAPIClient/CacheKeyCreator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Web; 4 | 5 | namespace BuffettCodeAPIClient 6 | { 7 | public class CacheKeyCreator 8 | { 9 | public static string Create(string baseUrl, ApiGetRequest request) 10 | { 11 | 12 | var paramsStr = String.Join("&", request.Parameters.Select(kv => $"{HttpUtility.UrlEncode(kv.Key)}={HttpUtility.UrlEncode(kv.Value)}").OrderBy(str => str)); 13 | return $"api/{baseUrl}/{request.EndPoint}?{paramsStr}"; 14 | } 15 | 16 | } 17 | } -------------------------------------------------------------------------------- /BuffettCodeCommon/Exception/ApiResponseParserException.cs: -------------------------------------------------------------------------------- 1 | namespace BuffettCodeCommon.Exception 2 | { 3 | using System; 4 | public class ApiResponseParserException : BaseBuffettCodeException 5 | { 6 | public ApiResponseParserException() : base() 7 | { 8 | } 9 | 10 | 11 | public ApiResponseParserException(string message) : base(message) 12 | { 13 | } 14 | 15 | public ApiResponseParserException(string message, Exception inner) : base(message, inner) 16 | { 17 | 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /BuffettCodeCommon/Exception/PropertyNotFoundException.cs: -------------------------------------------------------------------------------- 1 | namespace BuffettCodeCommon.Exception 2 | { 3 | using System; 4 | public class PropertyNotFoundException : BaseBuffettCodeException 5 | { 6 | public PropertyNotFoundException() : base() 7 | { 8 | } 9 | 10 | 11 | public PropertyNotFoundException(string message) : base(message) 12 | { 13 | } 14 | 15 | public PropertyNotFoundException(string message, Exception inner) : base(message, inner) 16 | { 17 | 18 | } 19 | 20 | } 21 | } -------------------------------------------------------------------------------- /BuffettCodeCommon/Validator/ApiFyParameterValidator.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Config; 2 | using BuffettCodeCommon.Exception; 3 | 4 | namespace BuffettCodeCommon.Validator 5 | { 6 | public static class ApiFyParameterValidator 7 | { 8 | public static void Validate(string fyParam) 9 | { 10 | if (!PeriodRegularExpressionConfig.FiscalYearRequestRegex.IsMatch(fyParam)) 11 | { 12 | throw new ValidationError($"{fyParam} is not supported format for fiscal year"); 13 | } 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /BuffettCodeCommon/Validator/CSVOutputEncodingValidator.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Config; 2 | using BuffettCodeCommon.Exception; 3 | using System.Text; 4 | 5 | namespace BuffettCodeCommon.Validator 6 | { 7 | public class CSVOutputEncodingValidator 8 | { 9 | public static void Validate(Encoding encoding) 10 | { 11 | if (!TabularOutputEncoding.SupportedEncodings.Contains(encoding)) 12 | { 13 | throw new ValidationError($"encoding={encoding} is not supported."); 14 | } 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /scripts/run_all_tests.ps1: -------------------------------------------------------------------------------- 1 | $Env:BCApiKey= "sAJGq9JH193KiwnF947v74KnDYkO7z634LWQQfPY" 2 | VSTest.Console.exe ` 3 | .\BuffettCodeAddinRibbonTests\bin\Release\BuffettCodeAddinRibbonTests.dll ` 4 | .\BuffettCodeIOTests\bin\Release\BuffettCodeIOTests.dll ` 5 | .\BuffettCodeExcelFunctionsTest\bin\Release\BuffettCodeExcelFunctionsTest.dll ` 6 | .\BuffettCodeExcelFunctionsTests\bin\Release\BuffettCodeExcelFunctionsTests.dll ` 7 | .\BuffettCodeAPIClientTests\bin\Release\BuffettCodeAPIClientTests.dll ` 8 | .\BuffettCodeCommonTests\bin\Release\BuffettCodeCommonTests.dll ` 9 | -------------------------------------------------------------------------------- /BuffettCodeCommon/Exception/NotSupportedDataTypeException.cs: -------------------------------------------------------------------------------- 1 | namespace BuffettCodeCommon.Exception 2 | { 3 | using System; 4 | public class NotSupportedDataTypeException : BaseBuffettCodeException 5 | { 6 | public NotSupportedDataTypeException() : base() 7 | { 8 | } 9 | 10 | public NotSupportedDataTypeException(string message) : base(message) 11 | { 12 | } 13 | 14 | public NotSupportedDataTypeException(string message, Exception inner) : base(message, inner) 15 | { 16 | 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /BuffettCodeCommon/Validator/ApiFqParameterValidator.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Config; 2 | using BuffettCodeCommon.Exception; 3 | 4 | namespace BuffettCodeCommon.Validator 5 | { 6 | public static class ApiFqParameterValidator 7 | { 8 | public static void Validate(string fqParam) 9 | { 10 | if (!PeriodRegularExpressionConfig.FiscalQuarterRequestRegex.IsMatch(fqParam)) 11 | { 12 | throw new ValidationError($"{fqParam} is not supported format for fiscal quarter"); 13 | } 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /BuffettCodeAPIClient/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /BuffettCodeAPIClientTests/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /BuffettCodeCommon/Exception/AddinConfigurationException.cs: -------------------------------------------------------------------------------- 1 | namespace BuffettCodeCommon.Exception 2 | { 3 | using System; 4 | public class AddinConfigurationException : BaseBuffettCodeException 5 | { 6 | public AddinConfigurationException() 7 | { 8 | } 9 | 10 | public AddinConfigurationException(string message) 11 | : base(message) 12 | { 13 | } 14 | 15 | public AddinConfigurationException(string message, Exception inner) 16 | : base(message, inner) 17 | { 18 | } 19 | 20 | } 21 | } -------------------------------------------------------------------------------- /BuffettCodeAPIClient/IBuffettCodeApiClient.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Config; 2 | using Newtonsoft.Json.Linq; 3 | 4 | 5 | namespace BuffettCodeAPIClient 6 | { 7 | public interface IBuffettCodeApiClient 8 | { 9 | JObject Get(DataTypeConfig dataType, ITickerIntentParameter parameter, bool useOndemand, bool isConfigureAwait, bool useCache); 10 | JObject GetRange(DataTypeConfig dataType, TickerPeriodRangeParameter parameter, bool useOndemand, bool isConfigureAwait, bool useCache); 11 | string GetApiKey(); 12 | void UpdateApiKey(string apiKey); 13 | 14 | } 15 | } -------------------------------------------------------------------------------- /SetupAddinRibbon32/CleanupOnUninstall.wxs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /BuffettCodeAPIClient/ApiGetRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace BuffettCodeAPIClient 4 | { 5 | public class ApiGetRequest 6 | { 7 | public string EndPoint { get; } 8 | public Dictionary Parameters { get; } 9 | 10 | public ApiGetRequest(string endPoint, Dictionary parameters) 11 | { 12 | EndPoint = endPoint; 13 | Parameters = parameters; 14 | } 15 | 16 | public override string ToString() => $"EndPoint::{EndPoint}, Parameters::{string.Join(", ", Parameters)}"; 17 | } 18 | } -------------------------------------------------------------------------------- /BuffettCodeCommonTests/Validator/ApiKeyValidatorTests.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Exception; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | namespace BuffettCodeCommon.Validator.Tests 4 | { 5 | [TestClass()] 6 | public class ApiKeyValidatorTests 7 | { 8 | [TestMethod()] 9 | public void ValidateTest() 10 | { 11 | // test api token is valid 12 | ApiKeyValidator.Validate("sAJGq9JH193KiwnF947v74KnDYkO7z634LWQQfPY"); 13 | 14 | Assert.ThrowsException(() => ApiKeyValidator.Validate("abc")); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /BuffettCodeCommon/Exception/ValidationError.cs: -------------------------------------------------------------------------------- 1 | namespace BuffettCodeCommon.Exception 2 | { 3 | using System; 4 | 5 | /// 6 | /// Exception class for Validation Error. 7 | /// 8 | public class ValidationError : BaseBuffettCodeException 9 | { 10 | public ValidationError() 11 | { 12 | } 13 | 14 | public ValidationError(string message) 15 | : base(message) 16 | { 17 | } 18 | 19 | public ValidationError(string message, Exception inner) 20 | : base(message, inner) 21 | { 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /scripts/install_dependencies.ps1: -------------------------------------------------------------------------------- 1 | $Packages = ( 2 | "BuffettCodeAddinRibbon", 3 | "BuffettCodeAddinRibbonTests", 4 | "BuffettCodeIO", 5 | "BuffettCodeIOTests", 6 | "BuffettCodeInstaller", 7 | "InstallerCA", 8 | "BuffettCodeExcelFunctions", 9 | "BuffettCodeExcelFunctionsTest", 10 | "BuffettCodeExcelFunctionsTests", 11 | "BuffettCodeAPIClient", 12 | "BuffettCodeAPIClientTests", 13 | "BuffettCodeCommon", 14 | "BuffettCodeCommonTests" 15 | ) 16 | 17 | foreach($Pkg in $Packages) { 18 | echo "install package in $Pkg" 19 | nuget install $Pkg\packages.config -OutputDirectory packages 20 | } 21 | -------------------------------------------------------------------------------- /BuffettCodeIO/Parser/ApiResponseParserFactory.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Config; 2 | using BuffettCodeCommon.Exception; 3 | namespace BuffettCodeIO.Parser 4 | { 5 | public class ApiResponseParserFactory 6 | { 7 | public static IApiResponseParser Create(BuffettCodeApiVersion version) 8 | { 9 | switch (version) 10 | { 11 | case BuffettCodeApiVersion.Version3: 12 | return new ApiV3ResponseParser(); 13 | default: 14 | throw new NonSupportedApiVersionException($"api version={version} is not supported."); 15 | } 16 | 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /BuffettCodeCommon/Config/TabularOutputConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Text; 3 | 4 | namespace BuffettCodeCommon.Config 5 | { 6 | public enum TabularOutputDestination 7 | { 8 | NewCsvFile = 0, 9 | NewWorksheet = 1, 10 | TestNewCsvFile = 2, 11 | TestNewWorksheet = 3, 12 | } 13 | 14 | public static class TabularOutputEncoding 15 | { 16 | public readonly static Encoding UTF8 = Encoding.UTF8; 17 | public readonly static Encoding SJIS = Encoding.GetEncoding("shift_jis"); 18 | public readonly static HashSet SupportedEncodings = new HashSet { UTF8, SJIS }; 19 | } 20 | 21 | } -------------------------------------------------------------------------------- /BuffettCodeCommon/Period/LatestDayPeriod.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Config; 2 | using System.Collections.Generic; 3 | 4 | namespace BuffettCodeCommon.Period 5 | { 6 | public class LatestDayPeriod : IDailyPeriod 7 | { 8 | private static readonly LatestDayPeriod instance = new LatestDayPeriod(); 9 | private LatestDayPeriod() { } 10 | 11 | public static LatestDayPeriod GetInstance() => instance; 12 | 13 | public override string ToString() => "LatestDayPeriod"; 14 | 15 | public Dictionary ToV3Parameter() => new Dictionary() { { ApiRequestParamConfig.KeyDate, ApiRequestParamConfig.ValueLatest }, }; 16 | } 17 | } -------------------------------------------------------------------------------- /SetupExcelFunctions32/CleanupOnUninstall.wxs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /scripts/upload_new_installer.ps1: -------------------------------------------------------------------------------- 1 | Param([string] $InstallerFolderPath, $S3Bucket, $SubFolder) 2 | $InstallerArchiveName = "BuffettCodeExcelAddinInstaller.zip" 3 | $S3Uri = "s3://$S3Bucket/buffett-code-excel-addin/$SubFolder/$InstallerArchiveName" 4 | $InstallerArchiveFullPath = "$InstallerFolderPath\$InstallerArchiveName" 5 | 6 | 7 | $Compress = @{ 8 | Path = "$InstallerFolderPath\*.exe", "$InstallerFolderPath\*.msi", "$InstallerFolderPath\*.cab" 9 | CompressionLevel = "Fastest" 10 | DestinationPath = "$InstallerArchiveFullPath" 11 | } 12 | 13 | Compress-Archive @Compress 14 | 15 | Write-Output "upload an archive: $InstallerArchiveFullPath to $S3Uri" 16 | 17 | aws s3 cp $InstallerArchiveFullPath $S3Uri --quiet -------------------------------------------------------------------------------- /BuffettCodeAPIClient/IIntentParameter.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Period; 2 | using System.Collections.Generic; 3 | 4 | namespace BuffettCodeAPIClient 5 | { 6 | 7 | public interface IIntentParameter 8 | { 9 | IIntent GetIntent(); 10 | } 11 | 12 | public interface ITickerParameter 13 | { 14 | string GetTicker(); 15 | 16 | } 17 | 18 | public interface ITickerIntentParameter : IIntentParameter, ITickerParameter { } 19 | 20 | public interface IApiV2Parameter 21 | { 22 | Dictionary ToApiV2Parameters(); 23 | } 24 | 25 | public interface IApiV3Parameter 26 | { 27 | Dictionary ToApiV3Parameters(); 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /BuffettCodeCommon/Validator/MonthValidator.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Exception; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace BuffettCodeCommon.Validator 9 | { 10 | public static class MonthValidator 11 | { 12 | public static void Validate(uint maybeMonth) 13 | { 14 | if (maybeMonth <= 0) 15 | { 16 | throw new ValidationError($"month={maybeMonth} is too small."); 17 | } 18 | else if (maybeMonth > 13) 19 | { 20 | throw new ValidationError($"month={maybeMonth} is too large."); 21 | } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /BuffettCodeExcelFunctionsTest/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | [assembly: AssemblyTitle("BuffettCodeExcelFunctionsTest")] 5 | [assembly: AssemblyDescription("")] 6 | [assembly: AssemblyConfiguration("")] 7 | [assembly: AssemblyCompany("")] 8 | [assembly: AssemblyProduct("BuffettCodeExcelFunctionsTest")] 9 | [assembly: AssemblyCopyright("Copyright © 2021")] 10 | [assembly: AssemblyTrademark("")] 11 | [assembly: AssemblyCulture("")] 12 | 13 | [assembly: ComVisible(false)] 14 | 15 | [assembly: Guid("db6ac57e-12e1-4020-aba0-ad76f4066bb9")] 16 | 17 | // [assembly: AssemblyVersion("1.0.*")] 18 | [assembly: AssemblyVersion("1.0.0.0")] 19 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /BuffettCodeIO/TabularOutput/FormattedValueSelector.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeIO.Formatter; 2 | using BuffettCodeIO.Property; 3 | 4 | namespace BuffettCodeIO.TabularOutput 5 | { 6 | public class FormattedValueSelector 7 | { 8 | private readonly IApiResource apiResource; 9 | 10 | public FormattedValueSelector(IApiResource apiResource) 11 | { 12 | this.apiResource = apiResource; 13 | } 14 | public string Select(string propertyName) 15 | { 16 | var desc = apiResource.GetDescription(propertyName); 17 | var rawValue = apiResource.GetValue(propertyName); 18 | return PropertyFormatterFactory.Create(desc).Format(rawValue, desc); 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /BuffettCodeAPIClient/ApiGetResponseValidator.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Config; 2 | using BuffettCodeCommon.Exception; 3 | using Newtonsoft.Json.Linq; 4 | using System.Linq; 5 | 6 | namespace BuffettCodeAPIClient 7 | { 8 | public class ApiGetResponseValidator 9 | { 10 | public static void Validate(JObject json) 11 | { 12 | var message = json.Children().Where(t => t is JToken).Cast().Where(t => t.Path.Equals("message")).ToArray(); 13 | if (message.Count() > 0 && message.First().ToString().Contains(ApiErrorMessageConfig.TEST_API_CONSTRAINT)) 14 | { 15 | throw new TestAPIConstraintException(message.First().ToString()); 16 | } 17 | } 18 | 19 | } 20 | } -------------------------------------------------------------------------------- /SetupExcelFunctions32/ProductProperties.wxl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 1033 4 | BuffettCodeExcelFunctions 5 | BuffettCodeExcelFunctions 6 | Installer for BuffettCode ExcelFunctions Add-In 7 | BuffettCode 8 | (c) 2021 Buffett Code Inc. 9 | Uninstall !(loc.ProductName) 10 | !(loc.ProductName) 11 | 12 | -------------------------------------------------------------------------------- /BuffettCodeIO/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /BuffettCodeCommon/BuffettCodeExceptionFinder.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Exception; 2 | namespace BuffettCodeCommon 3 | { 4 | public static class BuffettCodeExceptionFinder 5 | { 6 | 7 | public static BaseBuffettCodeException Find(System.Exception e) 8 | { 9 | System.Exception cursor = e; 10 | // 例外によってはBuffettCodeExceptionがInnerExceptionに入ってくるので、 11 | // 再帰的にスキャンして取り出している 12 | do 13 | { 14 | if (cursor is BaseBuffettCodeException bce) 15 | { 16 | return bce; 17 | } 18 | cursor = cursor.InnerException; 19 | } while (cursor != null); 20 | return null; 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /BuffettCodeAddinRibbon/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /BuffettCodeIO/Formatter/InactionFormatter.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeIO.Property; 2 | namespace BuffettCodeIO.Formatter 3 | { 4 | /// 5 | /// 値をそのまま返すだけのフォーマッタ 6 | /// 7 | public class InactionFormatter : IPropertyFormatter 8 | { 9 | private static readonly InactionFormatter _instance = new InactionFormatter(); 10 | 11 | public static InactionFormatter GetInstance() 12 | { 13 | return _instance; 14 | } 15 | 16 | /// 17 | public string Format(string value, PropertyDescription description) 18 | { 19 | return value; 20 | } 21 | 22 | private InactionFormatter() 23 | { 24 | // do nothing. 25 | } 26 | 27 | } 28 | } -------------------------------------------------------------------------------- /BuffettCodeAPIClientTests/CacheKeyCreatorTests.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.TestTools.UnitTesting; 2 | using System.Collections.Generic; 3 | 4 | namespace BuffettCodeAPIClient.Tests 5 | { 6 | [TestClass()] 7 | public class CacheKeyCreatorTests 8 | { 9 | [TestMethod()] 10 | public void CreateTest() 11 | { 12 | var baseUrl = "baseUrl"; 13 | var endPoint = "dummy"; 14 | var parameters = new Dictionary { { "key", "value" }, { "キー", "バリュー" } }; 15 | var request = new ApiGetRequest(endPoint, parameters); 16 | Assert.AreEqual("api/baseUrl/dummy?%e3%82%ad%e3%83%bc=%e3%83%90%e3%83%aa%e3%83%a5%e3%83%bc&key=value", CacheKeyCreator.Create(baseUrl, request)); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /BuffettCodeCommonTests/Validator/CSVOutputEncodingValidatorTests.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Config; 2 | using BuffettCodeCommon.Exception; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | using System.Text; 5 | namespace BuffettCodeCommon.Validator.Tests 6 | { 7 | [TestClass()] 8 | public class CSVOutputEncodingValidatorTests 9 | { 10 | [TestMethod()] 11 | public void ValidateTest() 12 | { 13 | // valid 14 | CSVOutputEncodingValidator.Validate(TabularOutputEncoding.UTF8); 15 | CSVOutputEncodingValidator.Validate(TabularOutputEncoding.SJIS); 16 | // invalid 17 | Assert.ThrowsException(() => CSVOutputEncodingValidator.Validate(Encoding.UTF7)); 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /BuffettCodeAPIClientTests/ErrorMockApiClientCore.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Exception; 2 | using System.Threading.Tasks; 3 | 4 | namespace BuffettCodeAPIClient.Tests 5 | { 6 | class ErrorMockApiClientCore : IApiClientCore 7 | { 8 | private string apiKey; 9 | public ErrorMockApiClientCore(string apiKey) 10 | { 11 | this.apiKey = apiKey; 12 | } 13 | 14 | 15 | public Task Get(ApiGetRequest request, bool isConfigureAwait) 16 | { 17 | throw new BuffettCodeApiClientException(); 18 | } 19 | 20 | public string GetApiKey() => this.apiKey; 21 | public IApiClientCore SetApiKey(string apikey) 22 | { 23 | apiKey = apikey; 24 | return this; 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /BuffettCodeCommon/Validator/ApiKeyValidator.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Exception; 2 | using System.Text.RegularExpressions; 3 | namespace BuffettCodeCommon.Validator 4 | { 5 | public static class ApiKeyValidator 6 | { 7 | // api token: half-width alphanumeric, length = 40 8 | /// 9 | /// Defines the API_KEY_PATTTERN. 10 | /// 11 | private readonly static Regex ApiKeyPattern = new Regex(@"^([a-zA-Z0-9]{40})$", RegexOptions.Compiled); 12 | 13 | public static void Validate(string maybeApiKey) 14 | { 15 | if (!ApiKeyPattern.IsMatch(maybeApiKey)) 16 | { 17 | throw new ValidationError($"api key must be half-width alphanumeric, length = 40"); 18 | } 19 | } 20 | 21 | } 22 | } -------------------------------------------------------------------------------- /BuffettCodeAPIClientTests/ApiGetResponseValidatorTests.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Config; 2 | using BuffettCodeCommon.Exception; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | using Newtonsoft.Json.Linq; 5 | 6 | 7 | namespace BuffettCodeAPIClient.Tests 8 | { 9 | [TestClass()] 10 | public class ApiGetResponseValidatorTests 11 | { 12 | [TestMethod()] 13 | public void ValidateTest() 14 | { 15 | 16 | // valid case 17 | ApiGetResponseValidator.Validate(new JObject { ["message"] = "ok" }); 18 | 19 | // invalid case 20 | var error = ApiErrorMessageConfig.TEST_API_CONSTRAINT + "dummy"; 21 | Assert.ThrowsException(() => ApiGetResponseValidator.Validate(new JObject { ["message"] = error })); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /BuffettCodeAPIClientTests/MockApiClientCore.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace BuffettCodeAPIClient.Tests 4 | { 5 | class MockApiClientCore : IApiClientCore 6 | { 7 | public static readonly string Response = "{\"name\":\"John\", \"age\":30, \"car\":null}"; 8 | private string apiKey; 9 | public MockApiClientCore(string apiKey) 10 | { 11 | this.apiKey = apiKey; 12 | } 13 | 14 | 15 | 16 | public Task Get(ApiGetRequest request, bool isConfigureAwait) 17 | { 18 | return Task.FromResult(Response); 19 | } 20 | 21 | public string GetApiKey() => this.apiKey; 22 | public IApiClientCore SetApiKey(string apiKey) 23 | { 24 | this.apiKey = apiKey; 25 | return this; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /BuffettCodeIO/Formatter/IPropertyFormatter.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeIO.Property; 2 | namespace BuffettCodeIO.Formatter 3 | { 4 | /// 5 | /// バフェットコードのWebAPIから取得した値のフォーマッタ 6 | /// 7 | /// 8 | /// バフェットコードのWebAPIから取得した値は、 9 | /// たとえば売上高などの金額であれば48000000000、 10 | /// PERなどのマルチプルであれば9.262569903846154など、 11 | /// DBから取得した値そのままで、財務データの一般的な表記ではありません。 12 | /// そこで、項目定義を参照しながら適切な表記に直す機能をそれぞれの派生クラスに持たせています。 13 | /// 14 | public interface IPropertyFormatter 15 | { 16 | /// 17 | /// 値をフォーマットします。 18 | /// 19 | /// 値 20 | /// 項目定義 21 | /// フォーマットされた値 22 | string Format(string value, PropertyDescription description); 23 | } 24 | } -------------------------------------------------------------------------------- /BuffettCodeExcelFunctions/BCodeUdfIntentValidator.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Config; 2 | using BuffettCodeCommon.Exception; 3 | 4 | 5 | namespace BuffettCodeExcelFunctions 6 | { 7 | public static class BCodeUdfIntentValidator 8 | { 9 | public static void Validate(string intent) 10 | { 11 | if (!( 12 | PeriodRegularExpressionConfig.BCodeUdfFiscalQuarterInputRegex.IsMatch(intent) || 13 | PeriodRegularExpressionConfig.BCodeUdfDailyInputRegex.IsMatch(intent) || 14 | PeriodRegularExpressionConfig.BCodeUdfMonthlyInputRegex.IsMatch(intent) || 15 | PeriodRegularExpressionConfig.BCodeUdfCompanyString == intent)) 16 | { 17 | throw new ValidationError($"{intent} is not supported period format for BCODE"); 18 | } 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /BuffettCodeAPIClientTests/ApiClientFactoryTest.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Config; 2 | using BuffettCodeCommon.Exception; 3 | 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | namespace BuffettCodeAPIClient.Tests 6 | { 7 | [TestClass()] 8 | public class ApiClientFactoryTest 9 | { 10 | [TestMethod()] 11 | public void CreateTest() 12 | { 13 | // v3 14 | var clientV3 = ApiClientFactory.Create(BuffettCodeApiVersion.Version3, BuffettCodeApiKeyConfig.TestApiKey); 15 | 16 | Assert.IsInstanceOfType(clientV3, typeof(BuffettCodeApiV3Client)); 17 | Assert.AreEqual(clientV3.GetApiKey(), BuffettCodeApiKeyConfig.TestApiKey); 18 | 19 | // api key validation error 20 | Assert.ThrowsException(() => ApiClientFactory.Create(BuffettCodeApiVersion.Version3, "dummy")); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /BuffettCodeAddinRibbon/Settings/CsvDownloadOutputSettings.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Config; 2 | using BuffettCodeCommon.Validator; 3 | using System.Text; 4 | namespace BuffettCodeAddinRibbon.Settings 5 | { 6 | 7 | public class CsvDownloadOutputSettings 8 | { 9 | public static CsvDownloadOutputSettings Create(Encoding encoding, TabularOutputDestination destination) 10 | { 11 | CSVOutputEncodingValidator.Validate(encoding); 12 | return new CsvDownloadOutputSettings(encoding, destination); 13 | } 14 | 15 | private CsvDownloadOutputSettings(Encoding encoding, TabularOutputDestination destination) 16 | { 17 | Encoding = encoding; 18 | Destination = destination; 19 | } 20 | public Encoding Encoding { get; set; } 21 | public TabularOutputDestination Destination { get; set; } 22 | 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /BuffettCodeCommon/Validator/FiscalYearValidator.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Exception; 2 | namespace BuffettCodeCommon.Validator 3 | { 4 | /// 5 | /// Defines the . 6 | /// 7 | public static class FiscalYearValidator 8 | { 9 | /// 10 | /// The Validate. 11 | /// 12 | /// The fiscalYear. 13 | public static void Validate(uint maybeFiscalYear) 14 | { 15 | if (maybeFiscalYear < 1900) 16 | { 17 | throw new ValidationError($"fiscalYear={maybeFiscalYear} is too small."); 18 | } 19 | else if (maybeFiscalYear > 2100) 20 | { 21 | throw new ValidationError($"fiscalYear={maybeFiscalYear} is too large."); 22 | } 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /BuffettCodeIOTests/Parser/PropertiesParserTests.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeAPIClient; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | using Newtonsoft.Json.Linq; 4 | using System.IO; 5 | using System.Linq; 6 | 7 | namespace BuffettCodeIO.Parser.Tests 8 | { 9 | [TestClass()] 10 | public class PropertiesParserTests 11 | { 12 | [TestMethod()] 13 | [DeploymentItem(@"TestData\Properties.json", @"TestData")] 14 | public void ParseTest() 15 | { 16 | var json = ApiGetResponseBodyParser.Parse(File.ReadAllText(@"TestData\Properties.json")).Cast(); 17 | var properties = PropertiesParser.Parse(json); 18 | Assert.AreEqual(properties.Get("company_name"), "株式会社カカクコム"); 19 | Assert.AreEqual(properties.Get("current_assets"), "28774000000"); 20 | Assert.AreEqual(properties.Get("prop_for_test.nested"), "12345"); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /BuffettCodeIO/Property/EmptyResource.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Period; 2 | using System.Collections.Generic; 3 | namespace BuffettCodeIO.Property 4 | { 5 | public class EmptyResource : IApiResource 6 | { 7 | private static readonly PropertyDescription emptyDescription = new PropertyDescription("", "", ""); 8 | 9 | private static readonly List emptyPropertyNames = new List(); 10 | 11 | private static readonly EmptyResource singleton = new EmptyResource(); 12 | 13 | private EmptyResource() { } 14 | 15 | public PropertyDescription GetDescription(string propertyName) => emptyDescription; 16 | public ICollection GetPropertyNames() => emptyPropertyNames; 17 | public string GetValue(string propertyName) => ""; 18 | 19 | public static EmptyResource GetInstance() => singleton; 20 | 21 | public IIntent GetPeriod() => Snapshot.GetInstance(); 22 | } 23 | } -------------------------------------------------------------------------------- /BuffettCodeIOTests/Formatter/MillionYenFormatterTests.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeIO.Property; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | namespace BuffettCodeIO.Formatter.Tests 5 | { 6 | [TestClass()] 7 | public class MillionYenFormatterTests 8 | { 9 | [TestMethod()] 10 | public void FormatTest() 11 | { 12 | var formatter = MillionYenFormatter.GetInstance(); 13 | var desc = new PropertyDescription("any", "any", "百万円"); 14 | 15 | // 四捨五入で小数点以下1桁に丸める 16 | Assert.AreEqual("100", formatter.Format("100,000,000", desc)); 17 | Assert.AreEqual("100,000", formatter.Format("100,000,000,000", desc)); 18 | Assert.AreEqual("-10", formatter.Format("-10,000,000.1", desc)); 19 | Assert.AreEqual("0.1", formatter.Format("100,000", desc)); 20 | Assert.AreEqual("0.2", formatter.Format("150,000.0", desc)); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /BuffettCodeAPIClientTests/ApiGetResponseReaderTests.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Config; 2 | using BuffettCodeCommon.Exception; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | using Newtonsoft.Json.Linq; 5 | 6 | namespace BuffettCodeAPIClient.Tests 7 | { 8 | [TestClass()] 9 | public class ApiGetResponseReaderTests 10 | { 11 | [TestMethod()] 12 | public void ReadTest() 13 | { 14 | // ok case 15 | var response = new JObject { ["message"] = "ok" }; 16 | Assert.AreEqual(response.ToString(), ApiGetResponseBodyParser.Parse(response.ToString()).ToString()); 17 | 18 | // ng case 19 | var error = ApiErrorMessageConfig.TEST_API_CONSTRAINT + "dummy"; 20 | var invalidResponse = new JObject { ["message"] = error }; 21 | Assert.ThrowsException(() => ApiGetResponseBodyParser.Parse(invalidResponse.ToString())); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /BuffettCodeIO/Property/SupportedPeriodRange.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Period; 2 | using System; 3 | 4 | namespace BuffettCodeIO.Property 5 | { 6 | public class SupportedTierRange where T : IComparablePeriod 7 | { 8 | private readonly PeriodRange fixedTierRange; 9 | private readonly PeriodRange ondemandTierRange; 10 | 11 | public SupportedTierRange( 12 | PeriodRange fixedTierRange, PeriodRange ondemandTierRange) 13 | { 14 | this.fixedTierRange = fixedTierRange; 15 | this.ondemandTierRange = ondemandTierRange; 16 | } 17 | 18 | public PeriodRange FixedTierRange => fixedTierRange; 19 | public PeriodRange OndemandTierRange => ondemandTierRange; 20 | 21 | public uint FixedTierRengeLength() => (uint)Math.Abs(fixedTierRange.TotalGap()); 22 | 23 | public uint OndemandTierRengeLength() => (uint)Math.Abs(ondemandTierRange.TotalGap()); 24 | 25 | } 26 | } -------------------------------------------------------------------------------- /BuffettCodeAddinRibbonTests/CsvDownload/CsvDownloadFormValidatorTests.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.TestTools.UnitTesting; 2 | 3 | namespace BuffettCodeAddinRibbon.CsvDownload.Tests 4 | { 5 | [TestClass()] 6 | public class CsvDownloadFormValidatorTests 7 | { 8 | [TestMethod()] 9 | public void ValidateFiscalQuarterTest() 10 | { 11 | // valid cases 12 | Assert.IsNull(CsvDownloadFormValidator.ValidateFiscalQuarter("2020Q1")); 13 | Assert.IsNull(CsvDownloadFormValidator.ValidateFiscalQuarter("2021Q4")); 14 | 15 | // invalid cases 16 | Assert.IsNotNull(CsvDownloadFormValidator.ValidateFiscalQuarter("2020Q6")); 17 | Assert.IsNotNull(CsvDownloadFormValidator.ValidateFiscalQuarter("2020")); 18 | Assert.IsNotNull(CsvDownloadFormValidator.ValidateFiscalQuarter("20Q3")); 19 | Assert.IsNotNull(CsvDownloadFormValidator.ValidateFiscalQuarter("20Q1st")); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /BuffettCodeAPIClient/ApiRequestLock.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Runtime.CompilerServices; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace BuffettCodeAPIClient 10 | { 11 | public class ApiRequestLock 12 | { 13 | private static readonly Dictionary lockObjects = new Dictionary(); 14 | 15 | 16 | [MethodImpl(MethodImplOptions.Synchronized)] 17 | public static object GetLockObject(ApiGetRequest request) 18 | { 19 | string lockKey = request.EndPoint; 20 | lockKey += String.Join("&", request.Parameters.Select(kv => $"{kv.Key}={kv.Value}").OrderBy(str => str)); 21 | 22 | if (!lockObjects.ContainsKey(lockKey)) 23 | { 24 | lockObjects[lockKey] = new object(); 25 | } 26 | 27 | return lockObjects[lockKey]; 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /BuffettCodeCommon/Period/ComparablePeriodUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace BuffettCodeCommon.Period 4 | { 5 | public class ComparablePeriodUtil 6 | { 7 | public static int GetGap(IIntent start, IIntent end) 8 | { 9 | if (start is FiscalQuarterPeriod sfq && end is FiscalQuarterPeriod efq) 10 | { 11 | return GetGap(sfq, efq); 12 | } 13 | else if (start is DayPeriod sd && end is DayPeriod ed) 14 | { 15 | return GetGap(sd, ed); 16 | } 17 | else 18 | { 19 | throw new NotImplementedException(); 20 | } 21 | } 22 | 23 | public static int GetGap(FiscalQuarterPeriod start, FiscalQuarterPeriod end) => (int)(end.Year - start.Year) * 4 + (int)(end.Quarter - start.Quarter); 24 | 25 | public static int GetGap(DayPeriod start, DayPeriod end) => (int)end.Value.Subtract(start.Value).TotalDays; 26 | 27 | } 28 | } -------------------------------------------------------------------------------- /BuffettCodeCommon/Validator/FiscalQuarterValidator.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Exception; 2 | namespace BuffettCodeCommon.Validator 3 | { 4 | using System.Collections.Generic; 5 | 6 | /// 7 | /// Defines the . 8 | /// 9 | public static class FiscalQuarterValidator 10 | { 11 | /// 12 | /// Defines the QUARTERS. 13 | /// 14 | private static readonly HashSet QUARTERS = new HashSet { 1, 2, 3, 4, 5 }; 15 | 16 | /// 17 | /// The Validate. 18 | /// 19 | /// The quarter. 20 | public static void Validate(uint maybeFiscalQuarter) 21 | { 22 | if (!QUARTERS.Contains(maybeFiscalQuarter)) 23 | { 24 | throw new ValidationError($"{maybeFiscalQuarter} is not in {QUARTERS}"); 25 | } 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /BuffettCodeExcelFunctions/BCodeExecutor.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Config; 2 | 3 | namespace BuffettCodeExcelFunctions 4 | { 5 | public class BCodeExecutor 6 | { 7 | private readonly ApiResourceFetcher fetcher; 8 | private readonly TickerIntentBuilder builder; 9 | 10 | public BCodeExecutor(BuffettCodeApiVersion version) 11 | { 12 | fetcher = new ApiResourceFetcher(version); 13 | builder = TickerIntentBuilder.Create(fetcher); 14 | } 15 | 16 | public string Execute(string ticker, DataTypeConfig dataType, string intent, string propertyName, bool isRawValue = false, bool isWithUnit = false) 17 | { 18 | var parameter = builder.SetTicker(ticker).SetIntent(intent).Build(); 19 | var apiResource = fetcher.Fetch(dataType, parameter, true, true); 20 | return PropertySelector.SelectFormattedValue(propertyName, apiResource, isRawValue, isWithUnit, true); 21 | } 22 | } 23 | 24 | 25 | 26 | 27 | } -------------------------------------------------------------------------------- /docs/overview.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | ## Packages 3 | `BuffettCode` ソリューションは下記の package を含みます 4 | 5 | 1. BuffettCodeAddinRibbon and Test 6 | 2. BuffettCodeAPIAdapter and Test 7 | 3. BuffettCodeExcelFunctions and Test 8 | 4. BuffettCodeInstaller 9 | 10 | ここでは、各 package の役割について簡単に説明します 11 | 12 | ### 1. BuffettCodeAddinRibbon 13 | バフェット・コードアドインの、Excel の「リボン」部分の実装です。 14 | - CSV出力やTokenの入力フォームを提供します 15 | - VSTO(Visual Studio Tools for Office)を利用しており、リリースビルドにはデジタル署名が必要です 16 | 17 | ### 2. BuffettCodeIO 18 | - [BuffettCode API](https://docs.buffett-code.com/)のclient, Formatter などデータの入出力を管理します 19 | - Registryの読み書きもここにあります 20 | 21 | ### 3. BuffetCodeExcelFunctions 22 | - [Excel-DNA](https://excel-dna.net/) を利用して、ExcelのUDFを作成しています 23 | - [Excel-XLL](https://docs.microsoft.com/ja-jp/office/client-developer/excel/developing-excel-xlls) が Build されます 24 | 25 | ### BuffettCodeInstaller 26 | BuffettCode Excel Addin は、上記の通り 27 | - VSTOで作られたExcelリボン 28 | - Excel-DNAで作られたUDF 29 | 30 | という、2つの異なる2つの成果物で成り立っています。 31 | インストーラは、この2つをそれぞれRegistryに配置します。 -------------------------------------------------------------------------------- /BuffettCodeAddinRibbon/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 6501 7 | 8 | 9 | 2016Q1 10 | 11 | 12 | 2018Q4 13 | 14 | 15 | True 16 | 17 | 18 | True 19 | 20 | 21 | -------------------------------------------------------------------------------- /BuffettCodeCommon/Config/ApiRequestParamConfig.cs: -------------------------------------------------------------------------------- 1 | namespace BuffettCodeCommon.Config 2 | { 3 | public static class ApiRequestParamConfig 4 | { 5 | // keys 6 | public static readonly string KeyTicker = "ticker"; 7 | public static readonly string KeyTickers = "tickers"; 8 | public static readonly string KeyFy = "fy"; 9 | public static readonly string KeyFq = "fq"; 10 | public static readonly string KeyFrom = "from"; 11 | public static readonly string KeyTo = "to"; 12 | public static readonly string KeyDate = "date"; 13 | public static readonly string KeyYear = "year"; 14 | public static readonly string KeyMonth = "month"; 15 | 16 | 17 | public static readonly string ValueLy = "LY"; 18 | public static readonly string ValueLq = "LQ"; 19 | public static readonly string ValueLatest = "latest"; 20 | // test api keyでも利用可能な "01" 銘柄を代表値として使う 21 | public static readonly string ValueRepresentativeJpTicker = "6501"; 22 | } 23 | } -------------------------------------------------------------------------------- /BuffettCodeIO/Formatter/MillionYenFormatter.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeIO.Property; 2 | using System; 3 | 4 | namespace BuffettCodeIO.Formatter 5 | { 6 | public class MillionYenFormatter : IPropertyFormatter 7 | { 8 | private static readonly MillionYenFormatter _instance = new MillionYenFormatter(); 9 | 10 | private MillionYenFormatter() 11 | { 12 | // do nothing 13 | } 14 | 15 | public static MillionYenFormatter GetInstance() => _instance; 16 | 17 | public string Format(string value, PropertyDescription description) 18 | { 19 | if (long.TryParse(value, out long l)) 20 | { 21 | return String.Format("{0:#,0}", l / 1000000); 22 | } 23 | else if (double.TryParse(value, out double d)) 24 | { 25 | return String.Format("{0:#,##0.#}", d / 1000000); 26 | } 27 | else 28 | { 29 | return value; 30 | } 31 | } 32 | 33 | } 34 | } -------------------------------------------------------------------------------- /BuffettCodeIO/Property/FixedTierRange.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Period; 2 | using System; 3 | 4 | namespace BuffettCodeIO.Property 5 | { 6 | public class FixedTierRange 7 | { 8 | private readonly FiscalQuarterPeriod oldestQuarter; 9 | private readonly FiscalQuarterPeriod latestQuarter; 10 | private readonly DayPeriod oldestDate; 11 | 12 | public FixedTierRange(FiscalQuarterPeriod oldestQuarter, FiscalQuarterPeriod latestQuarter, DayPeriod oldestDate 13 | ) 14 | { 15 | this.oldestQuarter = oldestQuarter; 16 | this.latestQuarter = latestQuarter; 17 | this.oldestDate = oldestDate; 18 | } 19 | 20 | public FiscalQuarterPeriod OldestQuarter => oldestQuarter; 21 | public FiscalQuarterPeriod LatestQuarter => latestQuarter; 22 | public DayPeriod OldestDate => oldestDate; 23 | 24 | // currently, latest date is always "today" 25 | public DayPeriod LatestDate => DayPeriod.Create(DateTime.Today); 26 | 27 | } 28 | } -------------------------------------------------------------------------------- /BuffettCodeAPIClient/ApiRequestCacheHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.Caching; 3 | 4 | namespace BuffettCodeAPIClient 5 | { 6 | public class ApiRequestCacheHelper 7 | { 8 | private readonly MemoryCache cache; 9 | private readonly string baseUrl; 10 | private readonly CacheItemPolicy policy = new CacheItemPolicy(); 11 | 12 | public ApiRequestCacheHelper(MemoryCache memoryCache, Uri baseUri) 13 | { 14 | this.baseUrl = baseUri.ToString(); 15 | this.cache = memoryCache; 16 | } 17 | public bool HasCache(ApiGetRequest request) => cache.Contains(CacheKeyCreator.Create(baseUrl, request)); 18 | 19 | public object Get(ApiGetRequest request) => cache.Get(CacheKeyCreator.Create(baseUrl, request)); 20 | 21 | public ApiRequestCacheHelper Set(ApiGetRequest request, String value) 22 | { 23 | cache.Set(CacheKeyCreator.Create(baseUrl, request), value, policy); 24 | return this; 25 | } 26 | 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /BuffettCodeExcelFunctionsTests/PropertyNameResolverTests.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeExcelFunctions; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | using System; 4 | 5 | namespace BuffettCodeExcelFunctionsTests 6 | { 7 | [TestClass] 8 | public class PropertyNameResolverTests 9 | { 10 | [TestMethod] 11 | public void ResolveTest() 12 | { 13 | Assert.AreEqual(PropertyNameResolver.Resolve("ticker"), "ticker"); 14 | Assert.AreEqual(PropertyNameResolver.Resolve("year"), "year"); 15 | Assert.AreEqual(PropertyNameResolver.Resolve("fiscal_year"), "fiscal_year"); 16 | Assert.AreEqual(PropertyNameResolver.Resolve("fiscal_quarter"), "fiscal_quarter"); 17 | Assert.AreEqual(PropertyNameResolver.Resolve("2y_beta"), "beta.years_2.beta"); 18 | Assert.AreEqual(PropertyNameResolver.Resolve("3y_beta_count"), "beta.years_3.count"); 19 | Assert.AreEqual(PropertyNameResolver.Resolve("beta.years_2.beta"), "beta.years_2.beta"); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /BuffettCodeCommon/Validator/TickerValidator.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Exception; 2 | namespace BuffettCodeCommon.Validator 3 | { 4 | using System.Text.RegularExpressions; 5 | 6 | /// 7 | /// Defines the . 8 | /// 9 | public static class JpTickerValidator 10 | { 11 | // jp ticker: 1000 - 9999 12 | /// 13 | /// Defines the TICKER_PATTTERN. 14 | /// 15 | private readonly static Regex TICKER_PATTTERN = new Regex("^[1-9][0-9]{3}$", RegexOptions.Compiled); 16 | 17 | /// 18 | /// The Validate. 19 | /// 20 | /// The maybeTicker. 21 | public static void Validate(string maybeTicker) 22 | { 23 | if (!TICKER_PATTTERN.IsMatch(maybeTicker)) 24 | { 25 | throw new ValidationError($"ticker must be '1000' - '9999', but {maybeTicker} is given"); 26 | } 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /BuffettCodeCommonTests/Validator/FiscalQuarterValidatorTests.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Exception; 2 | namespace BuffettCodeCommon.Validator.Tests 3 | { 4 | using BuffettCodeCommon.Validator; 5 | using Microsoft.VisualStudio.TestTools.UnitTesting; 6 | using System.Collections.Generic; 7 | 8 | /// 9 | /// Defines the . 10 | /// 11 | [TestClass()] 12 | public class FiscalQuarterValidatorTests 13 | { 14 | /// 15 | /// The ValidateTest. 16 | /// 17 | [TestMethod()] 18 | public void ValidateTest() 19 | { 20 | // 1 - 5 is quarter, path validate method 21 | new List { 1, 2, 3, 4, 5 }.ForEach(q => FiscalQuarterValidator.Validate(q)); 22 | 23 | // error case, 0 or 6+ int 24 | Assert.ThrowsException(() => FiscalQuarterValidator.Validate(0)); 25 | 26 | 27 | Assert.ThrowsException(() => FiscalQuarterValidator.Validate(6)); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /BuffettCodeIO/Formatter/PropertyFormatterFactory.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeIO.Property; 2 | namespace BuffettCodeIO.Formatter 3 | { 4 | 5 | public static class PropertyFormatterFactory 6 | { 7 | public static IPropertyFormatter Create(PropertyDescription description = null) 8 | { 9 | if (description == null) 10 | { 11 | return InactionFormatter.GetInstance(); 12 | } 13 | 14 | switch (description.Unit) 15 | { 16 | case "%": 17 | return RatioFormatter.GetInstance(); 18 | case "円": 19 | case "株": 20 | case "倍": 21 | case "日": 22 | case "ヶ月": 23 | case "人": 24 | return NumericFormatter.GetInstance(); 25 | case "百万円": 26 | return MillionYenFormatter.GetInstance(); 27 | case "年": 28 | default: 29 | return InactionFormatter.GetInstance(); 30 | } 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /docs/ci_settings.md: -------------------------------------------------------------------------------- 1 | # CI settings 2 | ## Build / Release Flow using github actions 3 | 1. Run CI by pushed or tagged for github 4 | - Branches except `master` trigger [Build](../.github/workflows/build.yml) 5 | - Tags named *v.X.Y.Z* and `master` branch trigger [Release](../.github/workflows/release.yml) 6 | 2. Run `MSBuild` and `VSTest` on Windows 2019 image on github action 7 | 3. Upload Installer to `s3` at BuffettCode AWS Account. 8 | 9 | ## Note 10 | - For normal build, use a **TEST** code signing certificate on this repo, [BuffettCodeTest.pfx](../BuffettCode/BuffettCodeTest.pfx) 11 | - For release build, use a Buffett Code signing certificate using github secrets variable. 12 | - Latest Master Branch's installer is here: [beta/latest](https://buffett-code-public-tools-ap-northeast-1.s3-ap-northeast-1.amazonaws.com/buffett-code-excel-addin/beta/latest/BuffettCodeExcelAddinInstaller.msi) 13 | - Tagged release build is here [release/*$tag*](https://buffett-code-public-tools-ap-northeast-1.s3-ap-northeast-1.amazonaws.com/buffett-code-excel-addin/release/$tag/BuffettCodeExcelAddinInstaller.msi) 14 | -------------------------------------------------------------------------------- /BuffettCodeCommonTests/Validator/ApiFyParameterValidatorTests.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Exception; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | namespace BuffettCodeCommon.Validator.Tests 4 | { 5 | [TestClass()] 6 | public class ApiFyParameterValidatorTests 7 | { 8 | [TestMethod()] 9 | public void ValidateTest() 10 | { 11 | // valid cases 12 | ApiFyParameterValidator.Validate("2020"); 13 | ApiFyParameterValidator.Validate("LY"); 14 | ApiFyParameterValidator.Validate("LY-1"); 15 | ApiFyParameterValidator.Validate("LY-10"); 16 | 17 | // invalid cases 18 | Assert.ThrowsException(() => ApiFyParameterValidator.Validate("")); 19 | Assert.ThrowsException(() => ApiFyParameterValidator.Validate("dummy")); 20 | Assert.ThrowsException(() => ApiFyParameterValidator.Validate("LQ")); 21 | Assert.ThrowsException(() => ApiFyParameterValidator.Validate("3")); 22 | 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /BuffettCodeAddinRibbon/ThisAddIn.Designer.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /BuffettCodeCommonTests/Validator/JpTickerValidatorTests.cs: -------------------------------------------------------------------------------- 1 | 2 | using BuffettCodeCommon.Exception; 3 | namespace BuffettCodeCommon.Validator.Tests 4 | { 5 | using BuffettCodeCommon.Validator; 6 | using Microsoft.VisualStudio.TestTools.UnitTesting; 7 | using System; 8 | using System.Collections.Generic; 9 | 10 | /// 11 | /// Defines the . 12 | /// 13 | [TestClass()] 14 | public class JpTickerValidatorTests 15 | { 16 | /// 17 | /// The TestJpTickerValidator. 18 | /// 19 | [TestMethod] 20 | public void TestJpTickerValidator() 21 | { 22 | var tickers = new List { "1000", "2000", "9999" }; 23 | tickers.ForEach(ticker => JpTickerValidator.Validate(ticker)); 24 | 25 | var nonTickers = new List { "999", "10000", "aaa" }; 26 | nonTickers.ForEach( 27 | noTicker => 28 | Assert.ThrowsException(() => JpTickerValidator.Validate(noTicker))); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /BuffettCodeCommonTests/Validator/FiscalYearValidatorTests.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Exception; 2 | namespace BuffettCodeCommon.Validator.Tests 3 | { 4 | using BuffettCodeCommon.Validator; 5 | using Microsoft.VisualStudio.TestTools.UnitTesting; 6 | using System.Collections.Generic; 7 | 8 | /// 9 | /// Defines the . 10 | /// 11 | [TestClass()] 12 | public class FiscalYearValidatorTests 13 | { 14 | /// 15 | /// The ValidateTest. 16 | /// 17 | [TestMethod()] 18 | public void ValidateTest() 19 | { 20 | // ok case 21 | new List { 1901, 2000, 2020, 2099 }.ForEach(q => FiscalYearValidator.Validate(q)); 22 | 23 | // error case 24 | Assert.ThrowsException(() => FiscalYearValidator.Validate(0)); 25 | Assert.ThrowsException(() => FiscalYearValidator.Validate(1899)); 26 | Assert.ThrowsException(() => FiscalYearValidator.Validate(2101)); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /BuffettCodeIO/Formatter/NumericFormatter.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeIO.Property; 2 | using System; 3 | 4 | namespace BuffettCodeIO.Formatter 5 | { 6 | /// 7 | /// 数値のフォーマッタ 8 | /// 9 | public class NumericFormatter : IPropertyFormatter 10 | { 11 | private static readonly NumericFormatter _instance = new NumericFormatter(); 12 | 13 | private NumericFormatter() 14 | { 15 | // do nothing. 16 | } 17 | 18 | /// 19 | public static NumericFormatter GetInstance() 20 | { 21 | return _instance; 22 | } 23 | 24 | public string Format(string value, PropertyDescription description) 25 | { 26 | if (long.TryParse(value, out long l)) 27 | { 28 | return String.Format("{0:#,0}", l); 29 | } 30 | else if (double.TryParse(value, out double d)) 31 | { 32 | return String.Format("{0:#,##0.#}", d); 33 | } 34 | else 35 | { 36 | return value; 37 | } 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /BuffettCodeAPIClient/ApiClientFactory.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon; 2 | using BuffettCodeCommon.Config; 3 | using BuffettCodeCommon.Exception; 4 | using BuffettCodeCommon.Validator; 5 | 6 | 7 | namespace BuffettCodeAPIClient 8 | { 9 | public class ApiClientFactory 10 | { 11 | private static BuffettCodeApiV3Client CreateV3(string apiKey) 12 | { 13 | var apiClientCore = ApiClientCoreWithCache.Create( 14 | apiKey, 15 | BuffettCodeApiV3Config.BASE_URL, 16 | BuffettCodeAddinCache.GetInstance() 17 | ); 18 | return new BuffettCodeApiV3Client(apiClientCore); 19 | } 20 | 21 | 22 | public static IBuffettCodeApiClient Create(BuffettCodeApiVersion version, string apiKey) 23 | { 24 | ApiKeyValidator.Validate(apiKey); 25 | switch (version) 26 | { 27 | case BuffettCodeApiVersion.Version3: 28 | return CreateV3(apiKey); 29 | default: 30 | throw new NonSupportedApiVersionException($"unknown version is given: {version}"); 31 | } 32 | } 33 | 34 | } 35 | } -------------------------------------------------------------------------------- /BuffettCodeExcelFunctions/DataTypeResolver.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Config; 2 | using BuffettCodeCommon.Exception; 3 | 4 | 5 | namespace BuffettCodeExcelFunctions 6 | { 7 | public class DataTypeResolver 8 | { 9 | public static DataTypeConfig Resolve(string intent) 10 | { 11 | if (PeriodRegularExpressionConfig.BCodeUdfDailyInputRegex.IsMatch(intent)) 12 | { 13 | return DataTypeConfig.Daily; 14 | } 15 | else if (PeriodRegularExpressionConfig.BCodeUdfFiscalQuarterInputRegex.IsMatch(intent)) 16 | { 17 | return DataTypeConfig.Quarter; 18 | } 19 | else if (PeriodRegularExpressionConfig.BCodeUdfMonthlyInputRegex.IsMatch(intent)) 20 | { 21 | return DataTypeConfig.Monthly; 22 | } 23 | else if (PeriodRegularExpressionConfig.BCodeUdfCompanyString == intent) 24 | { 25 | return DataTypeConfig.Company; 26 | } 27 | else 28 | { 29 | throw new ValidationError($"{intent} is not supported input format"); 30 | } 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /InstallerCA/InstallerClass.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace ExcelXLL 2 | { 3 | partial class InstallerClass 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | components = new System.ComponentModel.Container(); 32 | } 33 | 34 | #endregion 35 | } 36 | } -------------------------------------------------------------------------------- /BuffettCodeIO/TabularOutput/TabularRow.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeIO.Property; 2 | using System.Collections.Generic; 3 | 4 | namespace BuffettCodeIO.TabularOutput 5 | { 6 | public class TabularRow 7 | { 8 | private readonly string key; 9 | private readonly string name; 10 | private readonly string unit; 11 | private readonly IList values = new List(); 12 | 13 | private TabularRow(string key, string name, string unit) 14 | { 15 | this.key = key; 16 | this.name = name; 17 | this.unit = unit; 18 | } 19 | 20 | public string Key => key; 21 | 22 | public string Name => name; 23 | 24 | public string Unit => unit; 25 | 26 | public static TabularRow Create(string key, string name, string unit) => new TabularRow(key, name, unit); 27 | 28 | public static TabularRow Create(PropertyDescription desc) => new TabularRow(desc.Name, desc.JpName, desc.Unit); 29 | 30 | 31 | public TabularRow Add(string value) 32 | { 33 | values.Add(value); 34 | return this; 35 | } 36 | 37 | public IList Values => values; 38 | } 39 | } -------------------------------------------------------------------------------- /BuffettCodeIO/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // アセンブリに関する一般情報は以下の属性セットをとおして制御されます。 5 | // アセンブリに関連付けられている情報を変更するには、 6 | // これらの属性値を変更してください。 7 | [assembly: AssemblyTitle("BuffettCodeIO")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("BuffettCodeIO")] 12 | [assembly: AssemblyCopyright("Copyright © 2019")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // ComVisible を false に設定すると、このアセンブリ内の型は COM コンポーネントから 17 | // 参照できなくなります。COM からこのアセンブリ内の型にアクセスする必要がある場合は、 18 | // その型の ComVisible 属性を true に設定してください。 19 | [assembly: ComVisible(false)] 20 | 21 | // このプロジェクトが COM に公開される場合、次の GUID が typelib の ID になります 22 | [assembly: Guid("44a5bfab-acd6-492f-b0c6-29e0ea07a90a")] 23 | 24 | // アセンブリのバージョン情報は次の 4 つの値で構成されています: 25 | // 26 | // メジャー バージョン 27 | // マイナー バージョン 28 | // ビルド番号 29 | // Revision 30 | // 31 | // すべての値を指定するか、次を使用してビルド番号とリビジョン番号を既定に設定できます 32 | // 以下のように '*' を使用します: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /BuffettCodeAPIClientTests/ApiClientTestHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.Caching; 3 | 4 | namespace BuffettCodeAPIClient.Tests 5 | { 6 | class ApiClientTestHelper 7 | { 8 | private static string GenerateCacheKey() => new Random().Next().GetHashCode().ToString(); 9 | 10 | public static MemoryCache CreateCacheForCache() => new MemoryCache(GenerateCacheKey()); 11 | 12 | public static ApiRequestCacheHelper CreateCheHelperForTest() => 13 | new ApiRequestCacheHelper(CreateCacheForCache(), new Uri("http://example.com")); 14 | 15 | public static ApiClientCoreWithCache CreateMockApiClientCoreWithCache(string apiKey) 16 | { 17 | var clientCore = new MockApiClientCore(apiKey); 18 | var cacheHelper = CreateCheHelperForTest(); 19 | return ApiClientCoreWithCache.Create(clientCore, cacheHelper); 20 | } 21 | 22 | public static ApiClientCoreWithCache CreateErrorMockApiClientCoreWithCache(string apiKey) 23 | { 24 | var clientCore = new ErrorMockApiClientCore(apiKey); 25 | var cacheHelper = CreateCheHelperForTest(); 26 | return ApiClientCoreWithCache.Create(clientCore, cacheHelper); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /BuffettCodeAddinRibbon/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // アセンブリに関する一般情報は、以下の属性セットによって 5 | // 制御されます。アセンブリに関連付けられている情報を変更するには、 6 | // これらの属性値を変更します。 7 | [assembly: AssemblyTitle("BuffettCodeAddinRibbon")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("BuffettCodeAddinRibbon")] 12 | [assembly: AssemblyCopyright("Copyright © 2019")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // ComVisible を false に設定すると、COM コンポーネントがこのアセンブリ内のその型を認識 17 | // できなくなります。COM からこのアセンブリ内の型にアクセスする必要がある場合は、 18 | // その型の ComVisible 属性を true に設定します。 19 | [assembly: ComVisible(false)] 20 | 21 | // このプロジェクトが COM に公開される場合、次の GUID がタイプ ライブラリの ID になります 22 | [assembly: Guid("bcc55eea-bb6d-46a9-baf6-05d5a34ec010")] 23 | 24 | // アセンブリのバージョン情報は、以下の 4 つの値で構成されています: 25 | // 26 | // メジャー バージョン 27 | // マイナー バージョン 28 | // ビルド番号 29 | // リビジョン 30 | // 31 | // すべての値を指定するか、下のように '*' を使ってビルドおよびリビジョン番号を 32 | // 既定値にすることができます: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /BuffettCodeExcelFunctionsTests/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /docs/setup_windows_env.md: -------------------------------------------------------------------------------- 1 | # Set up your Windows Environment using Powershell 2 | ## Install .Net Freamwork and Wix 3 | - [install .Netfreamwork 3.5](https://dotnet.microsoft.com/download/dotnet-framework/net35-sp1) 4 | - [install Wix](https://github.com/wixtoolset/wix3/releases/tag/wix3112rtm) 5 | 6 | ## Install Visual Studio 2019 and extensions 7 | - [install Visual Studio 2019 with MsBuild](https://visualstudio.microsoft.com/downloads/) 8 | - [Wix Toolset Visual Studio 2019 Extension](https://marketplace.visualstudio.com/items?itemName=WixToolset.WixToolsetVisualStudio2019Extension) 9 | - [install Invoke MsBuild](https://www.powershellgallery.com/packages/Invoke-MsBuild/) 10 | 11 | ## Install scoop and build tools 12 | - [install scoop](https://scoop.sh) 13 | - [install ssh using scoop](https://github.com/lukesampson/scoop/wiki/SSH-on-Windows) 14 | - install git using scoop `scoop install git` 15 | - install nuget using scoop `scoop install nuget` 16 | - install wixtoolset using scoop `scoop install wixtoolset` 17 | 18 | # Install dependencies and build 19 | Execute following powershell cmd in a cloned folder. 20 | 21 | ```powershell 22 | # install dependencies 23 | .\scripts\install_dependencies.ps1 24 | 25 | # Run Build Command 26 | Invoke-MsBuild -Path .\BuffettCode.sln 27 | ``` 28 | -------------------------------------------------------------------------------- /BuffettCodeIOTests/Property/SupportedTierRangeTests.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Period; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | namespace BuffettCodeIO.Property.Tests 5 | { 6 | [TestClass()] 7 | public class SupportedTierRangeTests 8 | { 9 | [TestMethod()] 10 | public void FixedTierRengeLengthTest() 11 | { 12 | var from = FiscalQuarterPeriod.Create(2020, 1); 13 | var to = FiscalQuarterPeriod.Create(2021, 2); 14 | var range = PeriodRange.Create(from, to); 15 | 16 | var supportedTierRange = new SupportedTierRange(range, null); 17 | 18 | Assert.AreEqual((uint)5, supportedTierRange.FixedTierRengeLength()); 19 | } 20 | 21 | [TestMethod()] 22 | public void OndemandTierRengeLengthTest() 23 | { 24 | var from = FiscalQuarterPeriod.Create(2020, 1); 25 | var to = FiscalQuarterPeriod.Create(2021, 2); 26 | var range = PeriodRange.Create(from, to); 27 | 28 | var supportedTierRange = new SupportedTierRange(null, range); 29 | 30 | Assert.AreEqual((uint)5, supportedTierRange.OndemandTierRengeLength()); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /BuffettCodeIO/Formatter/RatioFormatter.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeIO.Property; 2 | using System; 3 | 4 | namespace BuffettCodeIO.Formatter 5 | { 6 | /// 7 | /// 割合のフォーマッタ 8 | /// 9 | public class RatioFormatter : IPropertyFormatter 10 | { 11 | private static readonly RatioFormatter _instance = new RatioFormatter(); 12 | 13 | private RatioFormatter() 14 | { 15 | // do nothing. 16 | } 17 | 18 | public static RatioFormatter GetInstance() 19 | { 20 | return _instance; 21 | } 22 | 23 | /// 24 | public string Format(string value, PropertyDescription description) 25 | { 26 | var format = GetFormat(description); 27 | return double.TryParse(value, out double d) ? String.Format(format, d) : value; 28 | } 29 | 30 | private string GetFormat(PropertyDescription description) 31 | { 32 | switch (description.Name) 33 | { 34 | case "dividend_yield_forecast": // 配当利回り(会社予想) 35 | case "dividend_yield_actual": // 配当利回り(実績) 36 | return "{0:f2}"; 37 | default: 38 | return "{0:f1}"; 39 | } 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /BuffettCodeCommonTests/Validator/ApiFqParameterValidatorTests.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Exception; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | namespace BuffettCodeCommon.Validator.Tests 4 | { 5 | [TestClass()] 6 | public class ApiFqParameterValidatorTests 7 | { 8 | [TestMethod()] 9 | public void ValidateTest() 10 | { 11 | // valid 12 | ApiFqParameterValidator.Validate("1"); 13 | ApiFqParameterValidator.Validate("2"); 14 | ApiFqParameterValidator.Validate("3"); 15 | ApiFqParameterValidator.Validate("4"); 16 | ApiFqParameterValidator.Validate("5"); 17 | ApiFqParameterValidator.Validate("LQ"); 18 | ApiFqParameterValidator.Validate("LQ-1"); 19 | ApiFqParameterValidator.Validate("LQ-20"); 20 | 21 | // invalid 22 | 23 | Assert.ThrowsException(() => ApiFqParameterValidator.Validate("")); 24 | Assert.ThrowsException(() => ApiFqParameterValidator.Validate("dummy")); 25 | Assert.ThrowsException(() => ApiFqParameterValidator.Validate("Q3")); 26 | Assert.ThrowsException(() => ApiFqParameterValidator.Validate("2020")); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /BuffettCodeIO/TabularOutput/CsvFileTabularWriter.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeIO.Property; 2 | using CsvHelper; 3 | using System.Globalization; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | 8 | 9 | namespace BuffettCodeIO.TabularOutput 10 | { 11 | public class CsvFileTabularWriter : ITabularWriter where T : IApiResource 12 | { 13 | private readonly CsvWriter writer; 14 | 15 | public CsvFileTabularWriter(Stream stream, Encoding encoding) 16 | { 17 | writer = new CsvWriter(new StreamWriter(stream, encoding), CultureInfo.InvariantCulture); 18 | } 19 | 20 | public void Dispose() 21 | { 22 | writer.Dispose(); 23 | } 24 | 25 | public void Write(Tabular output) 26 | { 27 | output.ToRows().ToList().ForEach(r => WriteRow(r)); 28 | writer.Flush(); 29 | } 30 | 31 | private void WriteRow(TabularRow row) 32 | { 33 | // write meta cols 34 | writer.WriteField(row.Key); 35 | writer.WriteField(row.Name); 36 | writer.WriteField(row.Unit); 37 | // write data cols 38 | row.Values.ToList().ForEach(v => writer.WriteField(v)); 39 | writer.NextRecord(); 40 | } 41 | 42 | } 43 | } -------------------------------------------------------------------------------- /BuffettCodeIO/Formatter/FormatterFactory.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeIO.Property; 2 | namespace BuffettCodeIO.Formatter 3 | { 4 | /// 5 | /// フォーマッタファクトリ 6 | /// 7 | public static class FormatterFactory 8 | { 9 | /// 10 | /// 使用すべきフォーマッタを返します。 11 | /// 12 | /// 項目定義 13 | /// フォーマッタ 14 | public static IPropertyFormatter Create(PropertyDescription description = null) 15 | { 16 | if (description == null) 17 | { 18 | return InactionFormatter.GetInstance(); 19 | } 20 | 21 | switch (description.Unit) 22 | { 23 | case "円": 24 | case "百万円": 25 | return CurrencyFormatter.GetInstance(); 26 | case "%": 27 | return RatioFormatter.GetInstance(); 28 | case "株": 29 | case "倍": 30 | case "日": 31 | case "ヶ月": 32 | case "人": 33 | return NumericFormatter.GetInstance(); 34 | case "年": 35 | default: 36 | return InactionFormatter.GetInstance(); 37 | } 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /BuffettCodeExcelFunctions/ApiResourceFetcher.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeAPIClient; 2 | using BuffettCodeCommon; 3 | using BuffettCodeCommon.Config; 4 | using BuffettCodeCommon.Period; 5 | using BuffettCodeIO; 6 | using BuffettCodeIO.Property; 7 | 8 | 9 | namespace BuffettCodeExcelFunctions 10 | { 11 | public class ApiResourceFetcher 12 | { 13 | 14 | private static readonly Configuration config = Configuration.GetInstance(); 15 | private readonly BuffettCodeApiTaskProcessor processor; 16 | 17 | public ApiResourceFetcher(BuffettCodeApiVersion version) 18 | { 19 | processor = new BuffettCodeApiTaskProcessor(version); 20 | } 21 | 22 | public IApiResource Fetch(DataTypeConfig dataType, ITickerIntentParameter parameter, bool isConfigureAwait, bool useCache) => processor.GetApiResource(dataType, parameter, isConfigureAwait, useCache); 23 | 24 | public FiscalQuarterPeriod FetchLatestFiscalQuarter(string ticker, bool isConfigureAwait, bool useCache) 25 | { 26 | var company = Fetch(DataTypeConfig.Company, TickerEmptyIntentParameter.Create(ticker, Snapshot.GetInstance()), isConfigureAwait, useCache) as Company; 27 | // use ondemand latest quarter period 28 | return company.SupportedQuarterRanges.OndemandTierRange.To; 29 | } 30 | 31 | } 32 | } -------------------------------------------------------------------------------- /BuffettCodeIO/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /BuffettCodeIOTests/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /BuffettCodeIO/Parser/FixedTierRangeParser.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Exception; 2 | using BuffettCodeCommon.Period; 3 | using BuffettCodeIO.Property; 4 | using Newtonsoft.Json.Linq; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | 9 | namespace BuffettCodeIO.Parser 10 | { 11 | public class FixedTierRangeParser 12 | { 13 | 14 | 15 | public static FixedTierRange Parse(IEnumerable jProperties) 16 | { 17 | try 18 | { 19 | var properties = jProperties.ToDictionary(p => p.Name, p => p.Value.ToString()); 20 | var oldestQuarter = FiscalQuarterPeriod.Create(properties[PropertyNames.OldestFiscalYear].ToString(), properties[PropertyNames.OldestFiscalQuarter].ToString()); 21 | var latestQuarter = FiscalQuarterPeriod.Create(properties[PropertyNames.LatestFiscalYear], properties[PropertyNames.LatestFiscalQuarter]); 22 | var oldestDate = DayPeriod.Create(DateTime.Parse(properties[PropertyNames.OldestDate])); 23 | 24 | return new FixedTierRange(oldestQuarter, latestQuarter, oldestDate); 25 | } 26 | catch (Exception e) 27 | { 28 | throw new ApiResponseParserException($"parse {PropertyNames.FixedTierRange} failed", e); 29 | } 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /BuffettCodeAddinRibbonTests/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /BuffettCodeExcelFunctions/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /BuffettCodeExcelFunctionsTest/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /BuffettCodeExcelFunctions/BuffettCodeExcelFunctions-AddIn.dna: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 23 | 24 | -------------------------------------------------------------------------------- /BuffettCodeAddinRibbon/CsvDownload/CsvDownloadFormValidator.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Exception; 2 | using BuffettCodeCommon.Validator; 3 | 4 | namespace BuffettCodeAddinRibbon.CsvDownload 5 | { 6 | public class CsvDownloadFormValidator 7 | { 8 | public static string ValidateFiscalQuarter(string fiscalPeriodParam) 9 | { 10 | var tokens = fiscalPeriodParam.Split('Q'); 11 | if (tokens.Length != 2) 12 | { 13 | return "フォーマットが正しくありません。'2017Q1'のように設定してください"; 14 | } 15 | else if (!uint.TryParse(tokens[0], out uint year)) 16 | { 17 | return "年が数値ではありません。"; 18 | } 19 | else if (!uint.TryParse(tokens[1], out uint quarter)) 20 | { 21 | return "四半期が数値ではありません。"; 22 | } 23 | else 24 | { 25 | try 26 | { 27 | FiscalYearValidator.Validate(year); 28 | } 29 | catch (ValidationError) { return $"年の設定が不正です: {year}"; } 30 | try 31 | { 32 | FiscalQuarterValidator.Validate(quarter); 33 | } 34 | catch (ValidationError) { return $"四半期の設定が不正です: {quarter}"; } 35 | } 36 | return null; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /BuffettCodeAddinRibbonTests/Settings/CsvDownloadDefaultParametersHandlerTests.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Config; 2 | using BuffettCodeCommon.Period; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | namespace BuffettCodeAddinRibbon.Settings.Tests 5 | { 6 | [TestClass()] 7 | public class CsvDownloadDefaultParametersHandlerTests 8 | { 9 | [TestMethod()] 10 | public void SaveAndLoadTest() 11 | { 12 | var ticker = "1234"; 13 | var from = FiscalQuarterPeriod.Create(2021, 1); 14 | var to = FiscalQuarterPeriod.Create(2022, 1); 15 | var outputSettings = CsvDownloadOutputSettings.Create(TabularOutputEncoding.SJIS, TabularOutputDestination.NewWorksheet); 16 | var newParams = CsvDownloadParameters.Create(ticker, from, to, outputSettings); 17 | CsvDownloadDefaultParametersHandler.Save(newParams); 18 | var loaded = CsvDownloadDefaultParametersHandler.Load(); 19 | Assert.AreEqual(ticker, loaded.Ticker); 20 | Assert.AreEqual(from, loaded.Range.From); 21 | Assert.AreEqual(to, loaded.Range.To); 22 | Assert.AreEqual(TabularOutputEncoding.SJIS, loaded.OutputSettings.Encoding); 23 | Assert.AreEqual(TabularOutputDestination.NewWorksheet 24 | , loaded.OutputSettings.Destination); 25 | } 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /BuffettCodeAddinRibbon/Settings/CsvDownloadParameters.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Config; 2 | using BuffettCodeCommon.Period; 3 | using BuffettCodeCommon.Validator; 4 | 5 | namespace BuffettCodeAddinRibbon.Settings 6 | { 7 | public class CsvDownloadParameters 8 | { 9 | 10 | private CsvDownloadParameters(string ticker, PeriodRange range, CsvDownloadOutputSettings outputSettings) 11 | { 12 | Ticker = ticker; 13 | Range = range; 14 | OutputSettings = outputSettings; 15 | } 16 | 17 | public static CsvDownloadParameters Create(string ticker, FiscalQuarterPeriod from, FiscalQuarterPeriod to, CsvDownloadOutputSettings outputSettings) 18 | { 19 | JpTickerValidator.Validate(ticker); 20 | var range = PeriodRange.Create(from, to); 21 | return new CsvDownloadParameters(ticker, range, outputSettings); 22 | } 23 | public string Ticker { get; set; } 24 | public PeriodRange Range { get; set; } 25 | 26 | public CsvDownloadOutputSettings OutputSettings { get; set; } 27 | public bool IsCreateNewFile() => OutputSettings.Destination is TabularOutputDestination.NewCsvFile; 28 | 29 | public bool IsUTF8Encoding() => OutputSettings.Encoding.Equals(TabularOutputEncoding.UTF8); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /BuffettCodeExcelFunctions/PropertyNameResolver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace BuffettCodeExcelFunctions 9 | { 10 | public class PropertyNameResolver 11 | { 12 | 13 | private static readonly ReadOnlyDictionary ITEM_NAME_ALIASES = new ReadOnlyDictionary(new Dictionary 14 | { 15 | {"2y_beta", "beta.years_2.beta"}, 16 | {"3y_beta", "beta.years_3.beta"}, 17 | {"5y_beta", "beta.years_5.beta"}, 18 | {"2y_beta_r2", "beta.years_2.r_squared"}, 19 | {"3y_beta_r2", "beta.years_3.r_squared"}, 20 | {"5y_beta_r2", "beta.years_5.r_squared"}, 21 | {"2y_beta_count", "beta.years_2.count"}, 22 | {"3y_beta_count", "beta.years_3.count"}, 23 | {"5y_beta_count", "beta.years_5.count"} 24 | }); 25 | 26 | 27 | public static string Resolve(string rawPropertyName) 28 | { 29 | if (ITEM_NAME_ALIASES.ContainsKey(rawPropertyName)) 30 | { 31 | return ITEM_NAME_ALIASES[rawPropertyName]; 32 | } 33 | else 34 | { 35 | return rawPropertyName; 36 | } 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /BuffettCodeAPIClientTests/PeriodRangeParameterTests.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Period; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | namespace BuffettCodeAPIClient.Tests 5 | { 6 | [TestClass()] 7 | public class PeriodRangeParameterTests 8 | { 9 | [TestMethod()] 10 | public void ToApiV2ParametersTest() 11 | { 12 | var ticker = "1234"; 13 | var from = FiscalQuarterPeriod.Create(2020, 1); 14 | var to = FiscalQuarterPeriod.Create(2020, 2); 15 | var parameter = TickerPeriodRangeParameter.Create(ticker, from, to).ToApiV2Parameters(); 16 | Assert.AreEqual(ticker, parameter["tickers"]); 17 | Assert.AreEqual(from.ToString(), parameter["from"]); 18 | Assert.AreEqual(to.ToString(), parameter["to"]); 19 | } 20 | 21 | [TestMethod()] 22 | public void ToApiV3ParametersTest() 23 | { 24 | var ticker = "1234"; 25 | var from = FiscalQuarterPeriod.Create(2020, 1); 26 | var to = FiscalQuarterPeriod.Create(2020, 2); 27 | var parameter = TickerPeriodRangeParameter.Create(ticker, from, to).ToApiV3Parameters(); 28 | Assert.AreEqual(ticker, parameter["ticker"]); 29 | Assert.AreEqual(from.ToString(), parameter["from"]); 30 | Assert.AreEqual(to.ToString(), parameter["to"]); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /SetupAddinRibbon32/ModRegistriesForAddin.wxs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /BuffettCodeIO/Parser/PropertyNames.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | namespace BuffettCodeIO.Parser 3 | { 4 | // API Response JSON key names 5 | class PropertyNames 6 | { 7 | public static readonly string Data = "data"; 8 | public static readonly string ColumnDescription = "column_description"; 9 | public static readonly string Ticker = "ticker"; 10 | public static readonly string Day = "day"; 11 | public static readonly string Year = "year"; 12 | public static readonly string Month = "month"; 13 | public static readonly string FiscalYear = "fiscal_year"; 14 | public static readonly string FiscalQuarter = "fiscal_quarter"; 15 | public static readonly string NameJp = "name_jp"; 16 | public static readonly string Unit = "unit"; 17 | public static readonly string FixedTierRange = "fixed_tier_range"; 18 | public static readonly string OldestFiscalYear = "oldest_fiscal_year"; 19 | public static readonly string OldestFiscalQuarter = "oldest_fiscal_quarter"; 20 | public static readonly string LatestFiscalYear = "latest_fiscal_year"; 21 | public static readonly string LatestFiscalQuarter = "latest_fiscal_quarter"; 22 | public static readonly string OldestDate = "oldest_date"; 23 | 24 | public static readonly HashSet IgnoredPropertyNames = new HashSet { FixedTierRange }; 25 | } 26 | } -------------------------------------------------------------------------------- /BuffettCodeCommon/Config/BuffettCodeRegistryConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | namespace BuffettCodeCommon.Registry 3 | { 4 | public static class BuffettCodeRegistryConfig 5 | { 6 | 7 | public static readonly string SubKeyBuffettCodeExcelAddinRelease = @"Software\BuffettCode\ExcelAddin"; 8 | public static readonly string SubKeyBuffettCodeExcelAddinDev = @"Software\BuffettCode\ExcelAddinDev"; 9 | 10 | public static string SubKeyBuffettCodeExcelAddinTest 11 | = @"Software\BuffettCode\ExcelAddinTest"; 12 | 13 | public static readonly string NameApiKey = "ApiKey"; 14 | 15 | public static readonly string NameIsOndemandEndpointEnabled = "IsOndemandEndpointEnabled"; 16 | 17 | public static readonly string NameDebugMode = "DebugMode"; 18 | 19 | public static readonly string NameForceOndemandApi = "ForceOndemandApi"; 20 | 21 | public static readonly ISet SubKeys = new HashSet 22 | { 23 | SubKeyBuffettCodeExcelAddinRelease, 24 | SubKeyBuffettCodeExcelAddinDev, 25 | SubKeyBuffettCodeExcelAddinTest, 26 | }; 27 | 28 | public static readonly ISet SupportedValueNames = new HashSet 29 | { 30 | NameApiKey, 31 | NameIsOndemandEndpointEnabled, 32 | NameDebugMode, 33 | NameForceOndemandApi, 34 | }; 35 | 36 | } 37 | } -------------------------------------------------------------------------------- /BuffettCodeAPIClientTests/ApiRequestCacheHelperTests.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.TestTools.UnitTesting; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Runtime.Caching; 5 | 6 | namespace BuffettCodeAPIClient.Tests 7 | { 8 | [TestClass()] 9 | public class ApiRequestCacheHelperTests 10 | { 11 | [TestMethod()] 12 | public void TestCacheLifeCycle() 13 | { 14 | var cache = new MemoryCache("TestCacheLifeCycle"); 15 | var baseUrl = "https://example.com/test"; 16 | var cacheHelper = new ApiRequestCacheHelper(cache, new Uri(baseUrl)); 17 | var endPoint = "dummy"; 18 | var parameters = new Dictionary { { "key", "value" } }; 19 | var response = "results"; 20 | var request = new ApiGetRequest(endPoint, parameters); 21 | 22 | // at first, no cache 23 | Assert.IsFalse(cacheHelper.HasCache(request)); 24 | Assert.AreEqual(0, cache.GetCount()); 25 | 26 | // set and get 27 | cacheHelper.Set(request, response); 28 | Assert.IsTrue(cacheHelper.HasCache(request)); 29 | Assert.AreEqual(response, cacheHelper.Get(request)); 30 | Assert.AreEqual(1, cache.GetCount()); 31 | 32 | // dispose 33 | cache.Dispose(); 34 | Assert.IsFalse(cacheHelper.HasCache(request)); 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /InstallerCA/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("InstallerCA")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyCompany("")] 10 | [assembly: AssemblyProduct("InstallerCA")] 11 | [assembly: AssemblyCopyright("Copyright © 2013")] 12 | [assembly: AssemblyTrademark("")] 13 | [assembly: AssemblyCulture("")] 14 | 15 | // Setting ComVisible to false makes the types in this assembly not visible 16 | // to COM components. If you need to access a type in this assembly from 17 | // COM, set the ComVisible attribute to true on that type. 18 | [assembly: ComVisible(false)] 19 | 20 | // The following GUID is for the ID of the typelib if this project is exposed to COM 21 | [assembly: Guid("bd89da70-0317-4659-a58d-5789bc59af03")] 22 | 23 | // Version information for an assembly consists of the following four values: 24 | // 25 | // Major Version 26 | // Minor Version 27 | // Build Number 28 | // Revision 29 | // 30 | // You can specify all the values or you can default the Build and Revision Numbers 31 | // by using the '*' as shown below: 32 | // [assembly: AssemblyVersion("1.0.*")] 33 | [assembly: AssemblyVersion("1.0.0.0")] 34 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /BuffettCodeCommonTests/BuffettCodeExceptionFinderTests.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Exception; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | namespace BuffettCodeCommon.Tests 5 | { 6 | class ExceptionWrapper : System.Exception 7 | { 8 | public ExceptionWrapper(string message, System.Exception inner) : base(message, inner) { } 9 | } 10 | 11 | class TestBuffettCodeException : BaseBuffettCodeException { } 12 | 13 | [TestClass()] 14 | public class BuffettCodeExceptionFinderTests 15 | { 16 | [TestMethod()] 17 | public void FindTest() 18 | { 19 | // BuffettCodeException 20 | var bcException = new TestAPIConstraintException(); 21 | var bcExceptionWrapper = new ExceptionWrapper("dummy", bcException); 22 | var nonBcException = new System.Exception(); 23 | var nonBcExceptionWrapper = new ExceptionWrapper("dummy", nonBcException); 24 | 25 | Assert.AreEqual( 26 | bcException, 27 | BuffettCodeExceptionFinder.Find(bcException)); 28 | 29 | Assert.AreEqual( 30 | bcException, 31 | BuffettCodeExceptionFinder.Find(bcExceptionWrapper)); 32 | 33 | Assert.IsNull( 34 | BuffettCodeExceptionFinder.Find(nonBcException)); 35 | 36 | Assert.IsNull( 37 | BuffettCodeExceptionFinder.Find(nonBcExceptionWrapper)); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /BuffettCodeExcelAddin32Installer/Bundle.wxs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /BuffettCodeCommon/Config/PeriodRegularExpressionConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | 3 | namespace BuffettCodeCommon.Config 4 | { 5 | public static class PeriodRegularExpressionConfig 6 | { 7 | public static readonly Regex FiscalYearRequestRegex = new Regex(@"^([12]\d{3}|LY(\-(?[1-9]\d*))?)$"); 8 | 9 | public static readonly Regex FiscalQuarterRequestRegex = new Regex(@"^([1-5]|LQ(\-(?[1-9]\d*))?)$"); 10 | 11 | public static readonly Regex FiscalQuarterRegex = new Regex(@"^[12]\d{3}Q[1-5]$"); 12 | 13 | public static readonly Regex YearMonthRegex = new Regex(@"^(?[12]\d{3})-(?[01]\d)$"); 14 | 15 | public static readonly Regex DayRegex = new Regex(@"^[12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$"); 16 | 17 | public static readonly Regex RelativeFiscalQuarterRegex = new Regex(@"^LY(\-(?[1-9]\d*))?LQ(\-(?[1-9]\d*))?$"); 18 | 19 | public static readonly Regex BCodeUdfFiscalQuarterInputRegex = new Regex(@"^(?([12]\d{3}|LY(\-(?[1-9]\d*))?))(?(Q[1-5]|LQ(\-(?[1-9]\d*))?))$"); 20 | 21 | public static readonly Regex BCodeUdfDailyInputRegex = new Regex(@"^([12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01]))|(latest)$"); 22 | 23 | public static readonly Regex BCodeUdfMonthlyInputRegex = new Regex(@"^(?[12]\d{3})-(?[01]\d)$"); 24 | 25 | public static readonly string BCodeUdfCompanyString = "COMPANY"; 26 | } 27 | } -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Lint 3 | 4 | # 5 | # Documentation: 6 | # https://help.github.com/en/articles/workflow-syntax-for-github-actions 7 | # https://github.com/dotnet/format 8 | 9 | ############################# 10 | # Start the job on all push # 11 | ############################# 12 | on: 13 | push: 14 | branches: 15 | - '**' 16 | tags-ignore: 17 | - 'v*' # v* trigger release.yml 18 | 19 | ############### 20 | # Set the Job # 21 | ############### 22 | jobs: 23 | build: 24 | # Name the Job 25 | name: Lint Code Base 26 | # Set the agent to run on, Container action is only supported on Linux 27 | runs-on: windows-2019 28 | 29 | ################## 30 | # Load all steps # 31 | ################## 32 | steps: 33 | ########################## 34 | # Checkout the code base # 35 | ########################## 36 | - name: Configure git 37 | run: git config --global core.autocrlf false 38 | - name: Checkout Code 39 | uses: actions/checkout@v2 40 | with: 41 | # Full git history is needed to get a proper list of changed files within `super-linter` 42 | fetch-depth: 0 43 | 44 | - name: Install dotnet-format 45 | run: dotnet tool install -g dotnet-format --version 5.1.* --add-source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json 46 | 47 | - name: Lint 48 | run: dotnet-format --check -v d -------------------------------------------------------------------------------- /BuffettCodeExcelFunctions/PropertySelector.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Config; 2 | using BuffettCodeIO.Formatter; 3 | using BuffettCodeIO.Property; 4 | 5 | namespace BuffettCodeExcelFunctions 6 | { 7 | public class PropertySelector 8 | { 9 | public static string SelectFormattedValue(string propertyName, IApiResource apiResource, bool isRawValue = false, bool isWithUnit = false, bool useDefaultUnit = false) 10 | { 11 | string rawValue = apiResource.GetValue(propertyName); 12 | 13 | var description = apiResource.GetDescription(propertyName); 14 | 15 | if (isRawValue) 16 | { 17 | return isWithUnit ? rawValue + description.Unit : rawValue; 18 | } 19 | else 20 | { 21 | 22 | if (useDefaultUnit) 23 | { 24 | // 定義済みの「円」単位の数値は 100万円に変換する 25 | if (DefaultUnitConfig.MillionYenProperties.Contains(description.Name) && description.Unit.Equals("円")) 26 | { 27 | description = new PropertyDescription(description.Name, description.JpName, "百万円"); 28 | } 29 | } 30 | 31 | var formatter = PropertyFormatterFactory.Create(description); 32 | string formattedValue = formatter.Format(rawValue, description); 33 | 34 | return isWithUnit ? formattedValue + description.Unit : formattedValue; 35 | } 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /BuffettCodeCommon/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("BuffettCodeCommon")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("BuffettCodeCommon")] 13 | [assembly: AssemblyCopyright("Copyright © 2021")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("8552cfd4-39c4-47d9-a0fa-be33b952465a")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /BuffettCodeAPIClient/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("BuffettCodeAPIClient")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("BuffettCodeAPIClient")] 12 | [assembly: AssemblyCopyright("Copyright © 2021")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("79daca04-c2b5-4d1b-996d-2ea1ad79909f")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /BuffettCodeExcelFunctions/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ExcelFunctions")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ExcelFunctions")] 13 | [assembly: AssemblyCopyright("Copyright © 2021")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("5de695f0-1e03-4337-b8ce-c99eb350f6d7")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /BuffettCodeIOTests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("BuffettCodeIOTests")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("BuffettCodeIOTests")] 12 | [assembly: AssemblyCopyright("Copyright © 2021")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("2be80093-91c5-461c-a244-99c5b7f67afa")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /BuffettCodeIOTests/TabularOutput/TabularRowTests.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeIO.Property; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | namespace BuffettCodeIO.TabularOutput.Tests 5 | { 6 | [TestClass()] 7 | public class TabularRowTests 8 | { 9 | private static readonly string key = "test_key"; 10 | private static readonly string name = "名前"; 11 | private static readonly string unit = "円"; 12 | 13 | [TestMethod()] 14 | public void CreateTest() 15 | { 16 | var row = TabularRow.Create(key, name, unit); 17 | Assert.AreEqual(key, row.Key); 18 | Assert.AreEqual(name, row.Name); 19 | Assert.AreEqual(unit, row.Unit); 20 | } 21 | 22 | [TestMethod()] 23 | public void CreateTest1() 24 | { 25 | var desc = new PropertyDescription(key, name, unit); 26 | var row = TabularRow.Create(desc); 27 | Assert.AreEqual(key, row.Key); 28 | Assert.AreEqual(name, row.Name); 29 | Assert.AreEqual(unit, row.Unit); 30 | } 31 | 32 | [TestMethod()] 33 | public void AddTest() 34 | { 35 | // add succeeded 36 | var row = TabularRow.Create(key, name, unit); 37 | var value = "dummy"; 38 | Assert.AreEqual(0, row.Values.Count); 39 | row.Add(value); 40 | Assert.AreEqual(1, row.Values.Count); 41 | Assert.AreEqual(value, row.Values[0]); 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /BuffettCodeCommonTests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("BuffettCodeCommonTests")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("BuffettCodeCommonTests")] 13 | [assembly: AssemblyCopyright("Copyright © 2021")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("e55d4f71-9aa4-435e-898a-7adb72fbba95")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /BuffettCodeAPIClientTests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("BuffettCodeAPIClientTests")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("BuffettCodeAPIClientTests")] 13 | [assembly: AssemblyCopyright("Copyright © 2021")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("5826fe1b-2227-462b-9a3c-af3434106028")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /BuffettCodeAddinRibbon/CsvDownload/ApiResourceGetter.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeAddinRibbon.Settings; 2 | using BuffettCodeCommon.Config; 3 | using BuffettCodeCommon.Period; 4 | using BuffettCodeIO; 5 | using BuffettCodeIO.Property; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | 9 | namespace BuffettCodeAddinRibbon.CsvDownload 10 | { 11 | public class ApiResourceGetter 12 | { 13 | private readonly BuffettCodeApiTaskProcessor processor; 14 | 15 | private ApiResourceGetter(BuffettCodeApiTaskProcessor processor) 16 | { 17 | this.processor = processor; 18 | } 19 | 20 | public static ApiResourceGetter Create() 21 | { 22 | var processor = new BuffettCodeApiTaskProcessor(BuffettCodeApiVersion.Version3); 23 | return new ApiResourceGetter(processor); 24 | } 25 | 26 | public IEnumerable GetQuarters(CsvDownloadParameters parameters) 27 | { 28 | 29 | // set isConfigureAwait for performance 30 | // https://devblogs.microsoft.com/dotnet/configureawait-faq/#why-would-i-want-to-use-configureawaitfalse 31 | var quarters = PeriodRange.Slice(parameters.Range, 4) 32 | .SelectMany 33 | (r => processor.GetApiResources(DataTypeConfig.Quarter, parameters.Ticker, r.From, r.To, false, true) 34 | ).Cast(); 35 | return quarters.Distinct().OrderBy(q => q.Period); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /BuffettCodeAddinRibbonTests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("BuffettCodeAddinRibbonTests")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("BuffettCodeAddinRibbonTests")] 12 | [assembly: AssemblyCopyright("Copyright © 2021")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("00a6a593-a87d-4dd2-8b06-8a36cfc6c3aa")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /BuffettCodeIO/Property/Daily.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Period; 2 | using BuffettCodeCommon.Validator; 3 | using System.Collections.Generic; 4 | 5 | 6 | namespace BuffettCodeIO.Property 7 | { 8 | public class Daily : IApiResource 9 | { 10 | private readonly string ticker; 11 | private readonly DayPeriod period; 12 | private readonly PropertyDictionary properties; 13 | private readonly PropertyDescriptionDictionary descriptions; 14 | 15 | private Daily(string ticker, DayPeriod period, PropertyDictionary properties, PropertyDescriptionDictionary descriptions) 16 | { 17 | this.ticker = ticker; 18 | this.period = period; 19 | this.properties = properties; 20 | this.descriptions = descriptions; 21 | } 22 | 23 | public DayPeriod Period => period; 24 | 25 | public PropertyDescription GetDescription(string propertyName) => descriptions.Get(propertyName); 26 | 27 | public IIntent GetPeriod() => period; 28 | 29 | public string Ticker => ticker; 30 | 31 | public ICollection GetPropertyNames() => properties.Names; 32 | public string GetValue(string propertyName) => properties.Get(propertyName); 33 | public static Daily Create(string ticker, DayPeriod period, PropertyDictionary properties, PropertyDescriptionDictionary descriptions) 34 | { 35 | JpTickerValidator.Validate(ticker); 36 | return new Daily(ticker, period, properties, descriptions); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /BuffettCodeExcelFunctionsTests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("BuffettCodeExcelFunctionsTests")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("BuffettCodeExcelFunctionsTests")] 12 | [assembly: AssemblyCopyright("Copyright © 2021")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("ad8a3f1e-584e-46c1-acee-a749433b99b2")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /BuffettCodeIO/Parser/PropertiesParser.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon; 2 | using BuffettCodeCommon.Exception; 3 | using BuffettCodeIO.Property; 4 | using Newtonsoft.Json.Linq; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | 9 | namespace BuffettCodeIO.Parser 10 | { 11 | public class PropertiesParser 12 | { 13 | public static PropertyDictionary Parse(IEnumerable jProperties) 14 | { 15 | try 16 | { 17 | var properties = FlattenProperties(jProperties); 18 | return new PropertyDictionary(properties); 19 | } 20 | catch (Exception e) 21 | { 22 | throw new ApiResponseParserException("parse properties failed", e); 23 | } 24 | } 25 | 26 | private static Dictionary FlattenProperties(IEnumerable jProperties) 27 | { 28 | var props = new List(); 29 | foreach (JToken root in jProperties) 30 | { 31 | Walk(root, n => props.Add(n as JProperty)); 32 | } 33 | return props.ToDictionary(p => p.Path, p => ValueNormalizer.Normalize(p.Value.ToString())); 34 | } 35 | 36 | private static void Walk(JToken node, Action action) 37 | { 38 | if (node is JProperty) 39 | { 40 | action(node); 41 | } 42 | foreach (JToken child in node.Children()) 43 | { 44 | Walk(child, action); 45 | } 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /BuffettCodeIO/Property/Monthly.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Period; 2 | using BuffettCodeCommon.Validator; 3 | using System.Collections.Generic; 4 | 5 | 6 | namespace BuffettCodeIO.Property 7 | { 8 | public class Monthly : IApiResource 9 | { 10 | private readonly string ticker; 11 | private readonly YearMonthPeriod period; 12 | private readonly PropertyDictionary properties; 13 | private readonly PropertyDescriptionDictionary descriptions; 14 | 15 | 16 | private Monthly(string ticker, YearMonthPeriod period, PropertyDictionary properties, PropertyDescriptionDictionary descriptions) 17 | { 18 | this.ticker = ticker; 19 | this.period = period; 20 | this.properties = properties; 21 | this.descriptions = descriptions; 22 | } 23 | 24 | public PropertyDescription GetDescription(string propertyName) => descriptions.Get(propertyName); 25 | 26 | public IIntent GetPeriod() => period; 27 | 28 | public string Ticker => ticker; 29 | 30 | 31 | public ICollection GetPropertyNames() => properties.Names; 32 | 33 | public string GetValue(string propertyName) => properties.Get(propertyName); 34 | 35 | public static Monthly Create(string ticker, uint year, uint month, PropertyDictionary properties, PropertyDescriptionDictionary descriptions) 36 | { 37 | JpTickerValidator.Validate(ticker); 38 | var period = YearMonthPeriod.Create(year, month); 39 | return new Monthly(ticker, period, properties, descriptions); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /Certificates/AAACertificateServices.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb 3 | MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow 4 | GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj 5 | YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL 6 | MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE 7 | BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM 8 | GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP 9 | ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua 10 | BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe 11 | 3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4 12 | YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR 13 | rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm 14 | ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU 15 | oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF 16 | MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v 17 | QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t 18 | b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF 19 | AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q 20 | GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz 21 | Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2 22 | G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi 23 | l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3 24 | smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== 25 | -----END CERTIFICATE----- 26 | -------------------------------------------------------------------------------- /BuffettCodeAddinRibbonTests/CsvDownload/ApiResourceGetterTests.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeAddinRibbon.Settings; 2 | using BuffettCodeCommon.Config; 3 | using BuffettCodeCommon.Period; 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | using System.Linq; 6 | 7 | 8 | namespace BuffettCodeAddinRibbon.CsvDownload.Tests 9 | { 10 | [TestClass()] 11 | public class ApiResourceGetterTests 12 | { 13 | public void CreateTest() 14 | { 15 | // default 16 | Assert.IsInstanceOfType( 17 | ApiResourceGetter.Create(), 18 | typeof(ApiResourceGetter) 19 | ); 20 | } 21 | 22 | [TestMethod()] 23 | public void GetQuartersTest() 24 | { 25 | var ticker = "6501"; 26 | var from = FiscalQuarterPeriod.Create(2020, 1); 27 | var to = FiscalQuarterPeriod.Create(2020, 2); 28 | var outputSettings = CsvDownloadOutputSettings.Create(TabularOutputEncoding.SJIS, TabularOutputDestination.NewWorksheet); 29 | var parameters = CsvDownloadParameters.Create(ticker, from, to, outputSettings); 30 | var quarters = ApiResourceGetter.Create().GetQuarters(parameters).ToArray(); 31 | var quarter2020Q1 = quarters[0]; 32 | var quarter2020Q2 = quarters[1]; 33 | Assert.AreEqual(2, quarters.Length); 34 | Assert.AreEqual(ticker, quarter2020Q1.Ticker); 35 | Assert.AreEqual(ticker, quarter2020Q2.Ticker); 36 | Assert.AreEqual(from, quarter2020Q1.Period); 37 | Assert.AreEqual(to, quarter2020Q2.Period); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /BuffettCodeIOTests/Property/PropertyDictionaryTests.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.TestTools.UnitTesting; 2 | using System.Collections.Generic; 3 | 4 | namespace BuffettCodeIO.Property.Tests 5 | { 6 | [TestClass()] 7 | public class PropertyContainerTests 8 | { 9 | 10 | private static readonly IDictionary properties = new Dictionary { { "key", "value" } }; 11 | 12 | 13 | [TestMethod()] 14 | public void EmptyTest() 15 | { 16 | var empty = PropertyDictionary.Empty(); 17 | Assert.AreEqual(0, empty.Count); 18 | 19 | } 20 | 21 | [TestMethod()] 22 | public void GetTest() 23 | { 24 | var container = new PropertyDictionary(properties); 25 | Assert.AreEqual("value", container.Get("key")); 26 | } 27 | 28 | [TestMethod()] 29 | public void EqualsTest() 30 | { 31 | var a = new PropertyDictionary(properties); 32 | var b = new PropertyDictionary(properties); 33 | var c = PropertyDictionary.Empty(); 34 | Assert.AreEqual(a, b); 35 | Assert.AreNotEqual(a, c); 36 | Assert.AreNotEqual(a, null); 37 | } 38 | 39 | [TestMethod()] 40 | public void GetHashCodeTest() 41 | { 42 | var a = new PropertyDictionary(properties).GetHashCode(); 43 | var b = new PropertyDictionary(properties).GetHashCode(); 44 | var c = PropertyDictionary.Empty().GetHashCode(); 45 | Assert.AreEqual(a, b); 46 | Assert.AreNotEqual(a, c); 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /BuffettCodeIOTests/Parser/ColumnDescriptionParserTests.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeAPIClient; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | using System.IO; 4 | 5 | namespace BuffettCodeIO.Parser.Tests 6 | { 7 | [TestClass()] 8 | public class ColumnDescriptionParserTests 9 | { 10 | [TestMethod()] 11 | [DeploymentItem(@"TestData\ColumnDescription.json", @"TestData")] 12 | public void ParseTest() 13 | { 14 | var json = ApiGetResponseBodyParser.Parse(File.ReadAllText(@"TestData\ColumnDescription.json")); 15 | var descriptions = ColumnDescriptionParser.Parse(json); 16 | var dividend = descriptions.Get("dividend"); 17 | Assert.AreEqual(dividend.Name, "dividend"); 18 | Assert.AreEqual(dividend.JpName, "配当金"); 19 | Assert.AreEqual(dividend.Unit, "円"); 20 | 21 | var ordinary_income = descriptions.Get("ordinary_income"); 22 | Assert.AreEqual(ordinary_income.Name, "ordinary_income"); 23 | Assert.AreEqual(ordinary_income.JpName, "経常利益"); 24 | Assert.AreEqual(ordinary_income.Unit, "百万円"); 25 | 26 | var nested1 = descriptions.Get("prop_for_test.nested_prop_1"); 27 | Assert.AreEqual(nested1.Name, "prop_for_test.nested_prop_1"); 28 | Assert.AreEqual(nested1.JpName, "ネストプロパティ1"); 29 | Assert.AreEqual(nested1.Unit, ""); 30 | 31 | var nested2 = descriptions.Get("prop_for_test.nested_prop_2"); 32 | Assert.AreEqual(nested2.Name, "prop_for_test.nested_prop_2"); 33 | Assert.AreEqual(nested2.JpName, "ネストプロパティ2"); 34 | Assert.AreEqual(nested2.Unit, "円"); 35 | 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /BuffettCodeAPIClient/BuffettCodeApiV3RequestCreator.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Config; 2 | 3 | 4 | namespace BuffettCodeAPIClient 5 | { 6 | public class BuffettCodeApiV3RequestCreator 7 | { 8 | public static ApiGetRequest CreateGetDailyRequest(TickerDayParameter parameter, bool useOndemand) 9 | { 10 | var endpoint = useOndemand ? 11 | BuffettCodeApiV3Config.ENDPOINT_ONDEMAND_DAILY : BuffettCodeApiV3Config.ENDPOINT_DAILY; 12 | 13 | return new ApiGetRequest(endpoint, parameter.ToApiV3Parameters()); 14 | } 15 | 16 | public static ApiGetRequest CreateGetQuarterRequest(TickerQuarterParameter parameter, bool useOndemand) 17 | { 18 | var endpoint = useOndemand ? 19 | BuffettCodeApiV3Config.ENDPOINT_ONDEMAND_QUARTER : BuffettCodeApiV3Config.ENDPOINT_QUARTER; 20 | 21 | return new ApiGetRequest(endpoint, parameter.ToApiV3Parameters()); 22 | } 23 | 24 | 25 | public static ApiGetRequest CreateGetQuarterRangeRequest(TickerPeriodRangeParameter parameter) 26 | { 27 | return new ApiGetRequest(BuffettCodeApiV3Config.ENDPOINT_BULK_QUARTER, parameter.ToApiV3Parameters()); 28 | } 29 | public static ApiGetRequest CreateGetCompanyRequest(TickerEmptyIntentParameter parameter) 30 | { 31 | return new ApiGetRequest(BuffettCodeApiV3Config.ENDPOINT_COMPANY, parameter.ToApiV3Parameters()); 32 | } 33 | public static ApiGetRequest CreateGetMonthlyRequest(TickerYearMonthParameter parameter) 34 | { 35 | return new ApiGetRequest(BuffettCodeApiV3Config.ENDPOINT_MONTHLY, parameter.ToApiV3Parameters()); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /BuffettCodeIO/TabularOutput/Tabular.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeIO.Property; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace BuffettCodeIO.TabularOutput 6 | 7 | { 8 | public class Tabular where T : IApiResource 9 | { 10 | private readonly TabularRow header = TabularRow.Create("キー", "項目名", "単位"); 11 | private readonly IDictionary rowDict = new Dictionary(); 12 | private readonly List keys = new List(); 13 | 14 | 15 | public Tabular Add(T apiResource) 16 | { 17 | // append header column using period 18 | header.Add(apiResource.GetPeriod().ToString()); 19 | var selector = new FormattedValueSelector(apiResource); 20 | // setup keys and values if empty 21 | if (keys.Count == 0) 22 | { 23 | // nest された json は対象外にする 24 | apiResource.GetPropertyNames().Where(name => !name.Contains(".")).ToList().ForEach(p => 25 | { 26 | keys.Add(p); 27 | rowDict.Add(p, TabularRow.Create(apiResource.GetDescription(p))); 28 | }); 29 | } 30 | 31 | // add each formatted values to the row 32 | keys.ForEach(p => rowDict[p].Add(selector.Select(p))); 33 | return this; 34 | } 35 | 36 | 37 | public IEnumerable ToRows() 38 | { 39 | // 1st row is header 40 | IList rows = new List { header }; 41 | // append rows by keys 42 | keys.ForEach(key => rows.Add(rowDict[key])); 43 | return rows; 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /BuffettCodeAPIClient/TickerEmptyIntentParameter.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Config; 2 | using BuffettCodeCommon.Period; 3 | using BuffettCodeCommon.Validator; 4 | using System.Collections.Generic; 5 | 6 | namespace BuffettCodeAPIClient 7 | { 8 | public class TickerEmptyIntentParameter : IApiV2Parameter, IApiV3Parameter, ITickerIntentParameter 9 | 10 | { 11 | private readonly string ticker; 12 | private readonly IIntent intent; 13 | 14 | private TickerEmptyIntentParameter(string ticker, IIntent intent) 15 | { 16 | this.ticker = ticker; 17 | this.intent = intent; 18 | } 19 | 20 | public IIntent GetIntent() => intent; 21 | 22 | public static TickerEmptyIntentParameter Create(string ticker, IIntent intent) 23 | { 24 | JpTickerValidator.Validate(ticker); 25 | return new TickerEmptyIntentParameter(ticker, intent); 26 | } 27 | 28 | public Dictionary ToApiV2Parameters() => new Dictionary() { { ApiRequestParamConfig.KeyTicker, ticker }, }; 29 | public Dictionary ToApiV3Parameters() => new Dictionary() { { ApiRequestParamConfig.KeyTicker, ticker }, }; 30 | 31 | public string GetTicker() => ticker; 32 | 33 | public override bool Equals(object obj) 34 | { 35 | if (obj is TickerEmptyIntentParameter tep) 36 | { 37 | return tep.ticker.Equals(ticker) && tep.intent.Equals(intent); 38 | } 39 | else 40 | { 41 | return false; 42 | } 43 | } 44 | 45 | public override int GetHashCode() => ticker.GetHashCode(); 46 | 47 | } 48 | } -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | # ref https://github.com/microsoft/setup-msbuild 2 | name: Build 3 | 4 | on: 5 | push: 6 | branches: 7 | # build at all branches except "master" 8 | - '**' 9 | - '!master' 10 | tags-ignore: 11 | - 'v*' # v* trigger release.yml 12 | jobs: 13 | build: 14 | runs-on: windows-2019 15 | env: 16 | S3_BUCKET: ${{ secrets.S3_INSTALLER_BUCKET }} 17 | GIT_BRANCH: ${{ github.ref }} 18 | INSTALLER_FOLDER: .\BuffettCodeExcelAddin32Installer\bin\Release 19 | steps: 20 | - uses: actions/checkout@v1 21 | - name: Setup MSBuild.exe 22 | uses: microsoft/setup-msbuild@v1.0.2 23 | - name: Setup VSTest Path 24 | uses: darenm/Setup-VSTest@v1 25 | - name: Install dependencies 26 | run: .\scripts\install_dependencies.ps1 27 | - name: Run MSBuild as Release mode 28 | run: MSBuild BuffettCode.sln /p:Configuration=Release 29 | - name: Run VSTest using Test API Token 30 | run: .\scripts\run_all_tests.ps1 31 | - name: Configure AWS credentials 32 | uses: aws-actions/configure-aws-credentials@v1 33 | with: 34 | aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} 35 | aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} 36 | aws-region: ap-northeast-1 37 | - name: Sign the built installer using test signing certificate 38 | run: ./scripts/sign_installer_for_build.ps1 .\Certificates\BuffettCodeTest.pfx "${{ env.INSTALLER_FOLDER }}\BuffettCodeExcelAddin32Installer.exe" 39 | - name: Upload new Installer to s3 40 | run: .\scripts\upload_new_installer.ps1 "$env:INSTALLER_FOLDER" "$env:S3_BUCKET" "$env:GIT_BRANCH".Replace('refs/heads', 'build/branches') -------------------------------------------------------------------------------- /BuffettCodeIOTests/Formatter/NumericFormatterTests.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeIO.Property; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | namespace BuffettCodeIO.Formatter.Tests 5 | { 6 | [TestClass()] 7 | public class NumericFormatterTests 8 | { 9 | [TestMethod] 10 | public void TestFormat() 11 | { 12 | var formatter = NumericFormatter.GetInstance(); 13 | var numeric = new PropertyDescription("any", "any", "株"); 14 | string formatted; 15 | 16 | // 整数 17 | formatted = formatter.Format("1", numeric); 18 | Assert.AreEqual("1", formatted); 19 | formatted = formatter.Format("10000", numeric); 20 | Assert.AreEqual("10,000", formatted); 21 | formatted = formatter.Format("-1000000", numeric); 22 | Assert.AreEqual("-1,000,000", formatted); 23 | formatted = formatter.Format("0", numeric); 24 | Assert.AreEqual("0", formatted); 25 | formatted = formatter.Format("", numeric); 26 | Assert.AreEqual("", formatted); 27 | 28 | // 小数 29 | // 四捨五入で小数点以下1桁に丸める 30 | formatted = formatter.Format("1.23456789", numeric); 31 | Assert.AreEqual("1.2", formatted); 32 | formatted = formatter.Format("12345.6789", numeric); 33 | Assert.AreEqual("12,345.7", formatted); 34 | formatted = formatter.Format("-999999.9", numeric); 35 | Assert.AreEqual("-999,999.9", formatted); 36 | formatted = formatter.Format("123.00000000", numeric); 37 | Assert.AreEqual("123", formatted); 38 | formatted = formatter.Format("0.0", numeric); 39 | Assert.AreEqual("0", formatted); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /BuffettCodeIO/TabularOutput/WorksheetTabularWriter.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeIO.Property; 2 | using Microsoft.Office.Interop.Excel; 3 | using System.Linq; 4 | 5 | namespace BuffettCodeIO.TabularOutput 6 | { 7 | public class WorksheetTabularWriter : ITabularWriter where T : IApiResource 8 | { 9 | 10 | private readonly Worksheet worksheet; 11 | 12 | public WorksheetTabularWriter(Worksheet worksheet) 13 | { 14 | this.worksheet = worksheet; 15 | } 16 | 17 | public void Dispose() 18 | { 19 | worksheet.Activate(); 20 | } 21 | 22 | public void Write(Tabular tabular) 23 | { 24 | uint rowIndex = 1; 25 | worksheet.Application.ScreenUpdating = false; 26 | var calcConfig = worksheet.Application.Calculation; 27 | worksheet.Application.Calculation = XlCalculation.xlCalculationManual; 28 | tabular.ToRows().ToList().ForEach(r => 29 | { 30 | WriteRow(rowIndex, r); 31 | rowIndex++; 32 | }); 33 | worksheet.Application.Calculation = calcConfig; 34 | worksheet.Application.ScreenUpdating = true; 35 | } 36 | 37 | private void WriteRow(uint rowNumber, TabularRow row) 38 | { 39 | // write meta cols 40 | worksheet.Cells[rowNumber, 1] = row.Key; 41 | worksheet.Cells[rowNumber, 2] = row.Name; 42 | worksheet.Cells[rowNumber, 3] = row.Unit; 43 | uint colNumber = 4; 44 | // write data cols 45 | row.Values.ToList().ForEach(v => 46 | { 47 | worksheet.Cells[rowNumber, colNumber] = v; 48 | colNumber++; 49 | }); 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /BuffettCodeExcelFunctionsTests/BCodeUdfIntentParameterValidatorTests.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Exception; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | namespace BuffettCodeExcelFunctions.Tests 5 | { 6 | [TestClass()] 7 | public class BCodeUdfIntentParameterValidatorTests 8 | { 9 | [TestMethod()] 10 | public void ValidateTest() 11 | { 12 | // valid cases 13 | BCodeUdfIntentValidator.Validate("2020Q1"); 14 | BCodeUdfIntentValidator.Validate("LYLQ"); 15 | BCodeUdfIntentValidator.Validate("LY-1LQ"); 16 | BCodeUdfIntentValidator.Validate("LYLQ-20"); 17 | BCodeUdfIntentValidator.Validate("LY-1LQ-20"); 18 | BCodeUdfIntentValidator.Validate("2019LQ-20"); 19 | BCodeUdfIntentValidator.Validate("LY-1Q3"); 20 | BCodeUdfIntentValidator.Validate("2012-12-12"); 21 | BCodeUdfIntentValidator.Validate("latest"); 22 | BCodeUdfIntentValidator.Validate("COMPANY"); 23 | // invalid cases 24 | Assert.ThrowsException(() => BCodeUdfIntentValidator.Validate("")); 25 | Assert.ThrowsException(() => BCodeUdfIntentValidator.Validate("dummy")); 26 | Assert.ThrowsException(() => BCodeUdfIntentValidator.Validate("2012/12/12")); 27 | Assert.ThrowsException(() => BCodeUdfIntentValidator.Validate("2020Q6")); 28 | Assert.ThrowsException(() => BCodeUdfIntentValidator.Validate("2020")); 29 | Assert.ThrowsException(() => BCodeUdfIntentValidator.Validate("Q3")); 30 | Assert.ThrowsException(() => BCodeUdfIntentValidator.Validate("company")); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /BuffettCodeExcelFunctionsTests/DataTypeResolverTests.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Config; 2 | using BuffettCodeCommon.Exception; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | namespace BuffettCodeExcelFunctions.Tests 5 | { 6 | [TestClass()] 7 | public class DataTypeResolverTests 8 | { 9 | [TestMethod()] 10 | public void ResolveTest() 11 | { 12 | // latest 13 | Assert.AreEqual(DataTypeConfig.Daily, DataTypeResolver.Resolve("latest")); 14 | 15 | // LYLQ 16 | Assert.AreEqual(DataTypeConfig.Quarter, DataTypeResolver.Resolve("LYLQ")); 17 | Assert.AreEqual(DataTypeConfig.Quarter, DataTypeResolver.Resolve("LY-1LQ")); 18 | Assert.AreEqual(DataTypeConfig.Quarter, DataTypeResolver.Resolve("LYLQ-1")); 19 | Assert.AreEqual(DataTypeConfig.Quarter, DataTypeResolver.Resolve("LY-1LQ-2")); 20 | Assert.AreEqual(DataTypeConfig.Quarter, DataTypeResolver.Resolve("2021LQ-2")); 21 | Assert.AreEqual(DataTypeConfig.Quarter, DataTypeResolver.Resolve("LY-1Q3")); 22 | 23 | // Quarter 24 | Assert.AreEqual(DataTypeConfig.Quarter, DataTypeResolver.Resolve("2020Q1")); 25 | 26 | // Daily 27 | Assert.AreEqual(DataTypeConfig.Daily, DataTypeResolver.Resolve("2020-01-01")); 28 | 29 | // Company 30 | Assert.AreEqual(DataTypeConfig.Company, DataTypeResolver.Resolve("COMPANY")); 31 | 32 | // Monthly 33 | Assert.AreEqual(DataTypeConfig.Monthly, DataTypeResolver.Resolve("2016-12")); 34 | Assert.AreEqual(DataTypeConfig.Monthly, DataTypeResolver.Resolve("2017-01")); 35 | 36 | // others 37 | Assert.ThrowsException(() => DataTypeResolver.Resolve("dummy")); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /BuffettCodeIO/Property/PropertyDescriptionDictionary.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace BuffettCodeIO.Property 5 | { 6 | 7 | public class PropertyDescriptionDictionary 8 | { 9 | private readonly IDictionary descriptions; 10 | 11 | public PropertyDescriptionDictionary(IDictionary descriptions) 12 | { 13 | this.descriptions = descriptions; 14 | } 15 | 16 | public static PropertyDescriptionDictionary Empty() 17 | { 18 | var empty = new Dictionary(); 19 | // return empty container 20 | return new PropertyDescriptionDictionary(empty); 21 | } 22 | 23 | public PropertyDescription Get(string propertyName) 24 | { 25 | return descriptions.Keys.Contains(propertyName) ? descriptions[propertyName] : PropertyDescription.Empty(); 26 | } 27 | public override bool Equals(object obj) 28 | { 29 | if (obj is null) 30 | { 31 | return false; 32 | } 33 | else if (this.GetType() != obj.GetType()) 34 | { 35 | return false; 36 | } 37 | else if (this.GetHashCode() != obj.GetHashCode()) 38 | { 39 | return false; 40 | } 41 | else 42 | { 43 | var pdc = (PropertyDescriptionDictionary)obj; 44 | return this.descriptions.SequenceEqual(pdc.descriptions); 45 | } 46 | } 47 | 48 | public override int GetHashCode() 49 | => 50 | descriptions.Sum(d => d.GetHashCode() / 1024).GetHashCode(); 51 | 52 | public int Count => descriptions.Count; 53 | } 54 | } -------------------------------------------------------------------------------- /BuffettCodeAddinRibbon/CsvDownload/CsvDownloadExceptionHandler.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon; 2 | using BuffettCodeCommon.Exception; 3 | 4 | namespace BuffettCodeAddinRibbon.CsvDownload 5 | { 6 | public class CsvDownloadExceptionHandler 7 | { 8 | 9 | private static bool IsDebugMode => Configuration.GetInstance().DebugMode; 10 | 11 | public static string ToMessageBoxString(BaseBuffettCodeException exception) 12 | { 13 | // if debug mode, return exception 14 | if (IsDebugMode) 15 | { 16 | return $"exception={exception}\nstack_trace={exception.StackTrace}"; 17 | } 18 | 19 | if (exception is TestAPIConstraintException) 20 | { 21 | return "テスト用のAPIキーでは末尾が01の銘柄コードのみ使用できます。"; 22 | } 23 | else if (exception is DailyQuotaException) 24 | { 25 | return "一日当たりのAPIの実行回数が上限に達しました。"; 26 | } 27 | else if (exception is InvalidAPIKeyException) 28 | { 29 | return $"APIキーが有効ではありません。"; 30 | } 31 | else if (exception is ApiResponseParserException) 32 | { 33 | return $"APIのレスポンスのパースに失敗しました。"; 34 | } 35 | else if (exception is NotSupportedTierException) 36 | { 37 | return $"取得可能な範囲を超えています。"; 38 | } 39 | else if (exception is ResourceNotFoundException) 40 | { 41 | return $"存在しないデータにアクセスしようとしています。"; 42 | } 43 | else if (exception is ApiMonthlyLimitExceededException) 44 | { 45 | return "今月のAPIの実行回数が上限に達しました。"; 46 | } 47 | else 48 | { 49 | return $"データの取得中にエラーが発生しました。"; 50 | } 51 | } 52 | 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /BuffettCodeAPIClientTests/ApiClientCoreTests.cs: -------------------------------------------------------------------------------- 1 | namespace BuffettCodeAPIClient.Tests 2 | { 3 | using BuffettCodeAPIClient; 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Net.Http; 8 | 9 | /// 10 | /// Defines the . 11 | /// 12 | [TestClass()] 13 | public class ApiClientCoreTests 14 | { 15 | /// 16 | /// The newHttpClientTest. 17 | /// 18 | [TestMethod()] 19 | public void NewHttpClientTest() 20 | { 21 | var apiKey = "dummy_api_key"; 22 | var baseUri = new Uri(@"https://example.com"); 23 | var clentCore 24 | = new ApiClientCore(apiKey, baseUri); 25 | // to test private method 26 | var privateObj = new PrivateObject(clentCore).Invoke("NewHttpClient"); 27 | 28 | Assert.IsInstanceOfType(privateObj, typeof(HttpClient)); 29 | HttpClient httpClient = (HttpClient)privateObj; 30 | var xApiKeyHeaders = new List(httpClient.DefaultRequestHeaders.GetValues("x-api-key")); 31 | Assert.AreEqual(baseUri, httpClient.BaseAddress); 32 | Assert.AreEqual(1, xApiKeyHeaders.Count); 33 | Assert.AreEqual(apiKey, xApiKeyHeaders[0]); 34 | } 35 | 36 | [TestMethod()] 37 | public void SetGetApiKeyTest() 38 | { 39 | var initKey = "init_api_key"; 40 | var newKey = "new_api_key"; 41 | var baseUri = new Uri(@"https://example.com"); 42 | var clientCore 43 | = new ApiClientCore(initKey, baseUri); 44 | Assert.AreEqual(initKey, clientCore.GetApiKey()); 45 | Assert.AreEqual(newKey, clientCore.SetApiKey(newKey).GetApiKey()); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /BuffettCodeAddinRibbon/Settings/CsvDownloadDefaultParametersHandler.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Config; 2 | using BuffettCodeCommon.Period; 3 | using BuffettCodeCommon.Validator; 4 | using System.Text; 5 | 6 | namespace BuffettCodeAddinRibbon.Settings 7 | { 8 | public static class CsvDownloadDefaultParametersHandler 9 | { 10 | public static CsvDownloadParameters Load() 11 | { 12 | var ticker = Properties.Settings.Default.CSVTicker; 13 | JpTickerValidator.Validate(ticker); 14 | var from = FiscalQuarterPeriod.Parse(Properties.Settings.Default.CSVFrom); 15 | var to = FiscalQuarterPeriod.Parse(Properties.Settings.Default.CSVTo); 16 | var outputSettings = LoadOutputSettings(); 17 | 18 | return CsvDownloadParameters.Create(ticker, from, to, outputSettings); 19 | } 20 | 21 | private static CsvDownloadOutputSettings LoadOutputSettings() 22 | { 23 | Encoding encoding = Properties.Settings.Default.CSVUTF8 ? 24 | TabularOutputEncoding.UTF8 : TabularOutputEncoding.SJIS; 25 | TabularOutputDestination destination = Properties.Settings.Default.CSVIsFile ? TabularOutputDestination.NewCsvFile : TabularOutputDestination.NewWorksheet; 26 | return CsvDownloadOutputSettings.Create(encoding, destination); 27 | } 28 | 29 | public static void Save(CsvDownloadParameters settings) 30 | { 31 | Properties.Settings.Default.CSVTicker = settings.Ticker; 32 | Properties.Settings.Default.CSVFrom = settings.Range.From.ToString(); 33 | Properties.Settings.Default.CSVTo = settings.Range.To.ToString(); 34 | Properties.Settings.Default.CSVIsFile = settings.IsCreateNewFile(); 35 | Properties.Settings.Default.CSVUTF8 = settings.IsUTF8Encoding(); 36 | Properties.Settings.Default.Save(); 37 | } 38 | 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /BuffettCodeIO/Property/PropertyDictionary.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Exception; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | namespace BuffettCodeIO.Property 5 | { 6 | public class PropertyDictionary 7 | { 8 | private readonly IDictionary properties; 9 | public PropertyDictionary(IDictionary properties) 10 | { 11 | this.properties = properties; 12 | } 13 | 14 | public static PropertyDictionary Empty() 15 | { 16 | var empty = new Dictionary(); 17 | return new PropertyDictionary(empty); 18 | } 19 | 20 | public string Get(string propertyName) 21 | { 22 | if (!properties.Keys.Contains(propertyName)) 23 | { 24 | throw new PropertyNotFoundException($"{propertyName} is not in {properties}"); 25 | } 26 | return properties[propertyName]; 27 | } 28 | 29 | public ICollection Names => properties.Keys; 30 | 31 | public override bool Equals(object obj) 32 | { 33 | if (obj is null) 34 | { 35 | return false; 36 | } 37 | else if (this.GetType() != obj.GetType()) 38 | { 39 | return false; 40 | } 41 | else if (this.GetHashCode() != obj.GetHashCode()) 42 | { 43 | return false; 44 | } 45 | { 46 | var pc = (PropertyDictionary)obj; 47 | return this.properties.SequenceEqual(pc.properties); 48 | } 49 | } 50 | 51 | public override int GetHashCode() 52 | { 53 | var kvStrArray = properties.OrderBy(p => p.Key).Select(p => $"{p.Key}:{p.Value}").ToArray(); 54 | return string.Join(", ", kvStrArray).GetHashCode(); 55 | } 56 | 57 | public int Count => properties.Count; 58 | 59 | } 60 | } -------------------------------------------------------------------------------- /BuffettCodeIOTests/TabularOutput/FormattedValueSelectorTests.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Period; 2 | using BuffettCodeIO.Property; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | using System.Collections.Generic; 5 | 6 | namespace BuffettCodeIO.TabularOutput.Tests 7 | { 8 | [TestClass()] 9 | public class FormattedValueSelectorTests 10 | { 11 | private static readonly string ticker = "1234"; 12 | private static readonly string key = "test_key"; 13 | private static readonly string value = "100000000000"; 14 | private static readonly string label = "ラベル"; 15 | private static readonly string unit = "百万円"; 16 | 17 | private static readonly FiscalQuarterPeriod period = FiscalQuarterPeriod.Create(2021, 3); 18 | private static readonly IDictionary properties = new Dictionary { { key, value } }; 19 | private static readonly IDictionary descriptions = new Dictionary { { key, new PropertyDescription(key, label, unit) } }; 20 | 21 | private static Quarter CreateQuarter(string ticker, FiscalQuarterPeriod period, IDictionary properties, IDictionary descriptions) 22 | { 23 | return Quarter.Create( 24 | ticker, 25 | period, 26 | properties is null ? PropertyDictionary.Empty() : new PropertyDictionary(properties), 27 | descriptions is null ? PropertyDescriptionDictionary.Empty() : new PropertyDescriptionDictionary(descriptions) 28 | ); 29 | } 30 | 31 | 32 | [TestMethod()] 33 | public void SelectQuarterTest() 34 | { 35 | var quarter = CreateQuarter(ticker, period, properties, descriptions); 36 | var selector = new FormattedValueSelector(quarter); 37 | Assert.AreEqual("100,000", selector.Select(key)); 38 | } 39 | 40 | 41 | } 42 | } -------------------------------------------------------------------------------- /BuffettCodeAPIClientTests/TickerYearMonthParameterTests.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Period; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | using System; 4 | 5 | namespace BuffettCodeAPIClient.Tests 6 | { 7 | [TestClass] 8 | public class TickerYearMonthParameterTests 9 | { 10 | [TestMethod] 11 | public void CreateTest() 12 | { 13 | var ticker = "1234"; 14 | var param = TickerYearMonthParameter.Create(ticker, YearMonthPeriod.Create(2022, 1)); 15 | Assert.AreEqual(ticker, param.GetTicker()); 16 | Assert.AreEqual("2022-01", param.GetIntent().ToString()); 17 | } 18 | 19 | [TestMethod()] 20 | public void ToApiV3ParametersTest() 21 | { 22 | var ticker = "1234"; 23 | var parameter1 = TickerYearMonthParameter.Create(ticker, YearMonthPeriod.Create(2017, 12)).ToApiV3Parameters(); 24 | 25 | Assert.AreEqual(ticker, parameter1["ticker"]); 26 | Assert.AreEqual("2017", parameter1["year"]); 27 | Assert.AreEqual("12", parameter1["month"]); 28 | } 29 | 30 | [TestMethod()] 31 | public void EqualsTest() 32 | { 33 | var a = TickerYearMonthParameter.Create("1234", YearMonthPeriod.Create(2015, 1)); 34 | var b = TickerYearMonthParameter.Create("1234", YearMonthPeriod.Create(2015, 1)); 35 | var c = TickerYearMonthParameter.Create("1234", YearMonthPeriod.Create(2015, 12)); 36 | var d = TickerYearMonthParameter.Create("1234", YearMonthPeriod.Create(2018, 5)); 37 | var e = TickerYearMonthParameter.Create("1234", YearMonthPeriod.Create(2018, 1)); 38 | 39 | Assert.AreEqual(a, b); 40 | Assert.AreNotEqual(a, c); 41 | Assert.AreNotEqual(a, d); 42 | Assert.AreNotEqual(a, e); 43 | Assert.AreNotEqual(c, b); 44 | Assert.AreNotEqual(c, d); 45 | Assert.AreNotEqual(c, e); 46 | Assert.AreNotEqual(d, e); 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /BuffettCodeIOTests/Property/PropertyDescriptionDictionaryTests.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.TestTools.UnitTesting; 2 | using System.Collections.Generic; 3 | 4 | namespace BuffettCodeIO.Property.Tests 5 | { 6 | [TestClass()] 7 | public class PropertyDescriptionContainerTests 8 | { 9 | private static readonly string name = "test_name"; 10 | private static readonly string label = "test_label"; 11 | private static readonly string unit = "test_unit"; 12 | private static readonly PropertyDescription description = new PropertyDescription(name, label, unit); 13 | private static readonly IDictionary descriptions = new Dictionary { { "key", description } }; 14 | 15 | [TestMethod()] 16 | public void EmptyTest() 17 | { 18 | var empty = PropertyDescriptionDictionary.Empty(); 19 | Assert.AreEqual(0, empty.Count); 20 | } 21 | 22 | [TestMethod()] 23 | public void GetTest() 24 | { 25 | var container = new PropertyDescriptionDictionary(descriptions); 26 | Assert.AreEqual(description, container.Get("key")); 27 | } 28 | 29 | [TestMethod()] 30 | public void EqualsTest() 31 | { 32 | var a = new PropertyDescriptionDictionary(descriptions); 33 | var b = new PropertyDescriptionDictionary(descriptions); 34 | var c = PropertyDescriptionDictionary.Empty(); 35 | 36 | Assert.AreEqual(a, b); 37 | Assert.AreNotEqual(a, c); 38 | } 39 | 40 | [TestMethod()] 41 | public void GetHashCodeTest() 42 | { 43 | var a = new PropertyDescriptionDictionary(descriptions).GetHashCode(); 44 | var b = new PropertyDescriptionDictionary(descriptions).GetHashCode(); 45 | var c = PropertyDescriptionDictionary.Empty().GetHashCode(); 46 | 47 | Assert.AreEqual(a, b); 48 | Assert.AreNotEqual(a, c); 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /SetupAddinRibbon32/Product.wxs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /BuffettCodeAddinRibbonTests/CsvDownload/TabularWriterBuilderTests.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeAddinRibbon.Settings; 2 | using BuffettCodeCommon.Config; 3 | using BuffettCodeCommon.Period; 4 | using BuffettCodeIO.Property; 5 | using BuffettCodeIO.TabularOutput; 6 | using Microsoft.VisualStudio.TestTools.UnitTesting; 7 | 8 | namespace BuffettCodeAddinRibbon.CsvDownload.Tests 9 | { 10 | [TestClass()] 11 | public class TabularWriterBuilderTests 12 | { 13 | private static readonly string ticker = "1234"; 14 | private static readonly FiscalQuarterPeriod from = FiscalQuarterPeriod.Create(2020, 1); 15 | private static readonly FiscalQuarterPeriod to = FiscalQuarterPeriod.Create(2020, 2); 16 | private readonly CsvDownloadOutputSettings newFileSettting = CsvDownloadOutputSettings.Create(TabularOutputEncoding.UTF8, TabularOutputDestination.TestNewCsvFile); 17 | private readonly CsvDownloadOutputSettings newSheetsetting = CsvDownloadOutputSettings.Create(TabularOutputEncoding.UTF8, TabularOutputDestination.TestNewWorksheet); 18 | 19 | private readonly TabularWriterBuilder quarterBuilder = new TabularWriterBuilder(); 20 | 21 | [TestMethod()] 22 | public void BuildQuarterCsvWriterTest() 23 | { 24 | var parameters = CsvDownloadParameters.Create(ticker, from, to, 25 | newFileSettting); 26 | var writer = quarterBuilder.Set(parameters).Build(); 27 | Assert.IsInstanceOfType(writer, typeof(CsvFileTabularWriter)); 28 | } 29 | 30 | // If you want test worksheet, comment in 31 | // On GitHub Actions, we can't use Windows Office now 32 | // [TestMethod()] 33 | public void BuildQuarterWorkseetTest() 34 | { 35 | var parameters = CsvDownloadParameters.Create(ticker, from, to, 36 | newSheetsetting); 37 | var writer = quarterBuilder.Set(parameters).Build(); 38 | Assert.IsInstanceOfType(writer, typeof(WorksheetTabularWriter)); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /BuffettCodeAPIClient/ApiClientCoreWithCache.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon; 2 | using System; 3 | using System.Runtime.Caching; 4 | 5 | namespace BuffettCodeAPIClient 6 | { 7 | public class ApiClientCoreWithCache 8 | { 9 | private readonly IApiClientCore apiClientCore; 10 | private readonly ApiRequestCacheHelper cacheHelper; 11 | 12 | private ApiClientCoreWithCache(IApiClientCore apiClientCore 13 | , ApiRequestCacheHelper cacheHelper) 14 | { 15 | this.apiClientCore = apiClientCore; 16 | this.cacheHelper = cacheHelper; 17 | } 18 | 19 | public static ApiClientCoreWithCache Create(string apiKey, string baseUrl, MemoryCache cache) 20 | { 21 | var baseUri = new Uri(baseUrl); 22 | var apiClientCore = new ApiClientCore(apiKey, baseUri); 23 | var cacheHelper = new ApiRequestCacheHelper(cache, baseUri); 24 | return new ApiClientCoreWithCache(apiClientCore, cacheHelper); 25 | } 26 | 27 | public static ApiClientCoreWithCache Create(IApiClientCore apiClientCore, ApiRequestCacheHelper cacheHelper) 28 | { 29 | return new ApiClientCoreWithCache(apiClientCore, cacheHelper); 30 | } 31 | 32 | public void UpdateApiKey(string apiKey) => this.apiClientCore.SetApiKey(apiKey); 33 | 34 | public string GetApiKey() => this.apiClientCore.GetApiKey(); 35 | 36 | public string Get(ApiGetRequest request, bool isConfigureAwait, bool useCache) 37 | { 38 | lock (ApiRequestLock.GetLockObject(request)) 39 | { 40 | if (useCache && cacheHelper.HasCache(request)) 41 | { 42 | return (string)cacheHelper.Get(request); 43 | } 44 | else 45 | { 46 | string result = apiClientCore.Get(request, isConfigureAwait).Result; 47 | cacheHelper.Set(request, result); 48 | return result; 49 | } 50 | } 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /BuffettCodeAPIClient/TickerPeriodRangeParameter.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Config; 2 | using BuffettCodeCommon.Period; 3 | using BuffettCodeCommon.Validator; 4 | using System.Collections.Generic; 5 | 6 | namespace BuffettCodeAPIClient 7 | { 8 | public class TickerPeriodRangeParameter : ITickerParameter, IApiV2Parameter, IApiV3Parameter 9 | { 10 | private readonly string ticker; 11 | private readonly PeriodRange periodRange; 12 | private TickerPeriodRangeParameter(string ticker, PeriodRange periodRange) 13 | { 14 | this.ticker = ticker; 15 | this.periodRange = periodRange; 16 | } 17 | 18 | public static TickerPeriodRangeParameter Create(string ticker, PeriodRange periodRange) 19 | { 20 | JpTickerValidator.Validate(ticker); 21 | return new TickerPeriodRangeParameter(ticker, periodRange); 22 | } 23 | 24 | public static TickerPeriodRangeParameter Create(string ticker, IComparablePeriod from, IComparablePeriod to) 25 | { 26 | JpTickerValidator.Validate(ticker); 27 | return new TickerPeriodRangeParameter(ticker, PeriodRange.Create(from, to)); 28 | } 29 | 30 | public string GetTicker() => ticker; 31 | 32 | public Dictionary ToApiV2Parameters() => new Dictionary{ 33 | {ApiRequestParamConfig.KeyTickers, ticker }, 34 | {ApiRequestParamConfig.KeyFrom, periodRange.From.ToString() }, 35 | {ApiRequestParamConfig.KeyTo, periodRange.To.ToString() }, 36 | }; 37 | 38 | public Dictionary ToApiV3Parameters() => new Dictionary{ 39 | {ApiRequestParamConfig.KeyTicker, ticker }, 40 | {ApiRequestParamConfig.KeyFrom, periodRange.From.ToString() }, 41 | {ApiRequestParamConfig.KeyTo, periodRange.To.ToString() }, 42 | }; 43 | 44 | public PeriodRange PeriodRange => periodRange; 45 | 46 | } 47 | } -------------------------------------------------------------------------------- /BuffettCodeIOTests/Property/PropertyDescriptionTests.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.TestTools.UnitTesting; 2 | 3 | namespace BuffettCodeIO.Property.Tests 4 | { 5 | [TestClass()] 6 | public class PropertyDescriptionTests 7 | { 8 | private static readonly string name = "test_name"; 9 | private static readonly string label = "test_label"; 10 | private static readonly string unit = "test_unit"; 11 | 12 | [TestMethod()] 13 | public void EmptyTest() 14 | { 15 | var empty = PropertyDescription.Empty(); 16 | Assert.AreEqual("", empty.Name); 17 | Assert.AreEqual("", empty.JpName); 18 | Assert.AreEqual("", empty.Unit); 19 | } 20 | 21 | [TestMethod()] 22 | public void GetHashCodeTest() 23 | { 24 | var a = new PropertyDescription(name, label, unit).GetHashCode(); 25 | var b = new PropertyDescription(name, label, unit).GetHashCode(); 26 | var c = new PropertyDescription("dummy", label, unit).GetHashCode(); 27 | var d = new PropertyDescription(name, "dummy", unit).GetHashCode(); 28 | var e = new PropertyDescription(name, label, "dummy").GetHashCode(); 29 | Assert.AreEqual(a, (name, label, unit).GetHashCode()); 30 | Assert.AreEqual(a, b); 31 | Assert.AreNotEqual(a, c); 32 | Assert.AreNotEqual(a, d); 33 | Assert.AreNotEqual(a, e); 34 | } 35 | 36 | [TestMethod()] 37 | public void EqualsTest() 38 | { 39 | var a = new PropertyDescription(name, label, unit); 40 | var b = new PropertyDescription(name, label, unit); 41 | var c = new PropertyDescription("dummy", label, unit); 42 | var d = new PropertyDescription(name, "dummy", unit); 43 | var e = new PropertyDescription(name, label, "dummy"); 44 | Assert.AreEqual(a, b); 45 | Assert.AreNotEqual(a, c); 46 | Assert.AreNotEqual(a, d); 47 | Assert.AreNotEqual(a, e); 48 | 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /BuffettCodeIO/Property/PropertyDescription.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | 3 | namespace BuffettCodeIO.Property 4 | { 5 | /// 6 | /// 項目の定義 7 | /// 8 | /// 9 | /// APIレスポンスのcolumn_descriptionに対応します。 10 | /// 11 | public class PropertyDescription 12 | { 13 | private static readonly string[] IGNORED_UNITS = { "なし", "単位無し" }; 14 | 15 | /// 16 | /// 項目名 17 | /// 18 | public string Name { get; set; } 19 | 20 | /// 21 | /// 日本語の名称 22 | /// 23 | public string JpName { get; set; } 24 | 25 | private string unit; 26 | 27 | /// 28 | /// 単位 29 | /// 30 | public string Unit 31 | { 32 | get { return IGNORED_UNITS.Contains(unit) ? "" : unit; } 33 | set { unit = value; } 34 | } 35 | 36 | public PropertyDescription(string name, string jpName, string unit) 37 | { 38 | Name = name; 39 | JpName = jpName; 40 | Unit = unit; 41 | } 42 | 43 | public static PropertyDescription Empty() 44 | { 45 | return new PropertyDescription("", "", ""); 46 | } 47 | 48 | public override int GetHashCode() => (Name, JpName, Unit).GetHashCode(); 49 | 50 | public override bool Equals(object obj) 51 | { 52 | if (obj is null) 53 | { 54 | return false; 55 | } 56 | else if (this.GetType() != obj.GetType()) 57 | { 58 | return false; 59 | } 60 | else if (this.GetHashCode() != obj.GetHashCode()) 61 | { 62 | return false; 63 | } 64 | else 65 | { 66 | var pd = (PropertyDescription)obj; 67 | return this.Name.Equals(pd.Name) 68 | && this.JpName.Equals(pd.JpName) 69 | && this.Unit.Equals(pd.Unit); 70 | } 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /BuffettCodeCommonTests/Period/ComparablePeriodUtilTests.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.TestTools.UnitTesting; 2 | 3 | namespace BuffettCodeCommon.Period.Tests 4 | { 5 | [TestClass()] 6 | public class ComparablePeriodUtilTests 7 | { 8 | [TestMethod()] 9 | public void GetGapTest() 10 | { 11 | // quarter 12 | var fq2020Q1 = FiscalQuarterPeriod.Create(2020, 1); 13 | var fq2020Q2 = FiscalQuarterPeriod.Create(2020, 2); 14 | Assert.AreEqual(1, ComparablePeriodUtil.GetGap(fq2020Q1, (IIntent)fq2020Q2)); 15 | 16 | // day 17 | var day20200101 = DayPeriod.Create(2020, 1, 1); 18 | var day20200102 = DayPeriod.Create(2020, 1, 2); 19 | Assert.AreEqual(1, ComparablePeriodUtil.GetGap(day20200101, (IIntent)day20200102)); 20 | } 21 | 22 | [TestMethod()] 23 | public void GetGapFiscalQuarterPeriodTest() 24 | { 25 | var fq2020Q1 = FiscalQuarterPeriod.Create(2020, 1); 26 | var fq2020Q2 = FiscalQuarterPeriod.Create(2020, 2); 27 | var fq2021Q1 = FiscalQuarterPeriod.Create(2021, 1); 28 | var fq2021Q4 = FiscalQuarterPeriod.Create(2021, 4); 29 | Assert.AreEqual(0, ComparablePeriodUtil.GetGap(fq2020Q1, fq2020Q1)); 30 | Assert.AreEqual(1, ComparablePeriodUtil.GetGap(fq2020Q1, fq2020Q2)); 31 | Assert.AreEqual(4, ComparablePeriodUtil.GetGap(fq2020Q1, fq2021Q1)); 32 | Assert.AreEqual(7, ComparablePeriodUtil.GetGap(fq2020Q1, fq2021Q4)); 33 | } 34 | 35 | [TestMethod()] 36 | public void GetGapDayPeriodTest() 37 | { 38 | var day20200101 = DayPeriod.Create(2020, 1, 1); 39 | var day20200102 = DayPeriod.Create(2020, 1, 2); 40 | var day20210101 = DayPeriod.Create(2021, 1, 1); 41 | Assert.AreEqual(0, ComparablePeriodUtil.GetGap(day20200101, day20200101)); 42 | Assert.AreEqual(1, ComparablePeriodUtil.GetGap(day20200101, day20200102)); 43 | Assert.AreEqual(366, ComparablePeriodUtil.GetGap(day20200101, day20210101)); 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /BuffettCodeCommon/Config/BuffettCodeApiConfig.cs: -------------------------------------------------------------------------------- 1 | namespace BuffettCodeCommon.Config 2 | { 3 | public enum BuffettCodeApiVersion 4 | { 5 | Version3 = 3, 6 | } 7 | public static class BuffettCodeApiKeyConfig 8 | { 9 | public static string TestApiKey = "sAJGq9JH193KiwnF947v74KnDYkO7z634LWQQfPY"; 10 | } 11 | 12 | public static class BuffettCodeApiV2Config 13 | { 14 | public static readonly string BASE_URL = "https://api.buffett-code.com/api/v2/"; 15 | public static readonly string ENDPOINT_QUARTER = "quarter"; 16 | public static readonly string ENDPOINT_ONDEMAND_QUARTER = "ondemand/quarter"; 17 | public static readonly string ENDPOINT_INDICATOR = "indicator"; 18 | public static readonly string ENDPOINT_DAILY = "daily"; 19 | public static readonly string ENDPOINT_COMPANY = "company"; 20 | } 21 | 22 | public static class BuffettCodeApiV3Config 23 | { 24 | public static readonly string BASE_URL = "https://api.buffett-code.com/api/v3/"; 25 | public static readonly string ENDPOINT_DAILY = "daily"; 26 | public static readonly string ENDPOINT_ONDEMAND_DAILY = "ondemand/daily"; 27 | public static readonly string ENDPOINT_BULK_DAILY = "bulk/daily"; 28 | public static readonly string ENDPOINT_QUARTER = "quarter"; 29 | public static readonly string ENDPOINT_ONDEMAND_QUARTER = "ondemand/quarter"; 30 | public static readonly string ENDPOINT_BULK_QUARTER = "bulk/quarter"; 31 | public static readonly string ENDPOINT_COMPANY = "company"; 32 | public static readonly string ENDPOINT_MONTHLY = "monthly"; 33 | } 34 | 35 | 36 | public static class ApiErrorMessageConfig 37 | { 38 | public static readonly string TEST_API_CONSTRAINT = "Testing Apikey is only allowed to ticker ending with"; 39 | } 40 | 41 | public static class ApiRelatedUrlConfig 42 | { 43 | public static readonly string API_SPECIAL_NOTES = "https://www.buffett-code.com/legal/web_api/special_notes"; 44 | public static readonly string ONDEMAND_API_USAGE_ENTRY = "https://blog.buffett-code.com/entry/ondemand_api_usage"; 45 | } 46 | 47 | } -------------------------------------------------------------------------------- /BuffettCodeExcelFunctions/TickerIntentBuilder.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeAPIClient; 2 | using BuffettCodeCommon.Period; 3 | using BuffettCodeCommon.Validator; 4 | using System.Collections.Generic; 5 | 6 | 7 | namespace BuffettCodeExcelFunctions 8 | { 9 | public class TickerIntentBuilder : ITickerIntentBuilder 10 | { 11 | private readonly ApiResourceFetcher fetcher; 12 | private string ticker; 13 | private string intent; 14 | private readonly Dictionary latestFiscalQuarters; 15 | 16 | 17 | private TickerIntentBuilder(ApiResourceFetcher fetcher, Dictionary latestFiscalQuarters) 18 | { 19 | this.fetcher = fetcher; 20 | this.latestFiscalQuarters = latestFiscalQuarters; 21 | } 22 | 23 | public static TickerIntentBuilder Create(ApiResourceFetcher fetcher) => new TickerIntentBuilder(fetcher, new Dictionary()); 24 | 25 | 26 | public static TickerIntentBuilder CreateForTest(ApiResourceFetcher fetcher, Dictionary latestFiscalQuarters) => new TickerIntentBuilder(fetcher, latestFiscalQuarters); 27 | 28 | 29 | public TickerIntentBuilder SetTicker(string ticker) 30 | { 31 | JpTickerValidator.Validate(ticker); 32 | this.ticker = ticker; 33 | return this; 34 | } 35 | 36 | public TickerIntentBuilder SetIntent(string intent) 37 | { 38 | this.intent = intent; 39 | return this; 40 | } 41 | 42 | private FiscalQuarterPeriod LatestFiscalQuarter 43 | { 44 | get 45 | { 46 | if (!latestFiscalQuarters.ContainsKey(ticker)) 47 | { 48 | var latest = fetcher.FetchLatestFiscalQuarter(ticker, true, true); 49 | latestFiscalQuarters.Add(ticker, latest); 50 | } 51 | return latestFiscalQuarters[ticker]; 52 | } 53 | } 54 | 55 | public ITickerIntentParameter Build() => TickerIntentCreator.Create(ticker, intent, LatestFiscalQuarter); 56 | 57 | } 58 | } -------------------------------------------------------------------------------- /BuffettCodeAddinRibbon/Ribbon.cs: -------------------------------------------------------------------------------- 1 | using BuffettCode; 2 | using BuffettCodeAddinRibbon.Settings; 3 | using BuffettCodeCommon; 4 | using BuffettCodeCommon.Exception; 5 | using Microsoft.Office.Tools.Ribbon; 6 | using System; 7 | using System.Windows.Forms; 8 | 9 | 10 | namespace BuffettCodeAddinRibbon 11 | { 12 | public partial class Ribbon 13 | { 14 | private void Ribbon_Load(object sender, RibbonUIEventArgs e) 15 | { 16 | 17 | } 18 | 19 | private void SettingButton_Click(object sender, RibbonControlEventArgs e) 20 | { 21 | var config = Configuration.GetInstance(); 22 | var configSettings = AddinSettings.Create(config); 23 | var form = new SettingForm(configSettings); 24 | form.ShowDialog(); 25 | if (form.DialogResult == DialogResult.OK) 26 | { 27 | try 28 | { 29 | var newSettings = AddinSettings.Create(form.GetAPIKey(), form.IsOndemandEndpointEnabled(), form.IsDebugMode(), form.IsForceOndemandEndpoint()); 30 | newSettings.SaveToConfiguration(config); 31 | } 32 | catch (Exception exp) 33 | { 34 | var bce = BuffettCodeExceptionFinder.Find(exp); 35 | if (bce is ValidationError) 36 | { 37 | MessageBox.Show("API KEYの値が間違っています", "設定", MessageBoxButtons.OK); 38 | } 39 | else 40 | { 41 | MessageBox.Show("設定が間違っています", "設定", MessageBoxButtons.OK); 42 | } 43 | } 44 | } 45 | } 46 | 47 | private void CSVButton_Click(object sender, RibbonControlEventArgs e) 48 | { 49 | CsvDownloadForm form = new CsvDownloadForm(); 50 | form.ShowDialog(); 51 | } 52 | 53 | private void RefreshButton_Click(object sender, RibbonControlEventArgs e) 54 | { 55 | BuffettCodeAddinCache.Dispose(); 56 | Globals.ThisAddIn.Application.CalculateFullRebuild(); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /BuffettCodeAPIClientTests/ApiClientCoreWithCacheTests.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon.Exception; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | using System.Collections.Generic; 4 | 5 | namespace BuffettCodeAPIClient.Tests 6 | { 7 | [TestClass()] 8 | public class ApiClientCoreWithCacheTests 9 | { 10 | private readonly ApiRequestCacheHelper cacheHelper = ApiClientTestHelper.CreateCheHelperForTest(); 11 | 12 | [TestMethod()] 13 | public void GetAndUpdateApiKeyTest() 14 | { 15 | var initApiKey = @"init-key"; 16 | var newApiKey = @"new-key"; 17 | var mockApiClientCore = new MockApiClientCore(initApiKey); 18 | var client = ApiClientCoreWithCache.Create(mockApiClientCore, cacheHelper); 19 | 20 | // test init value 21 | Assert.AreEqual(initApiKey, client.GetApiKey()); 22 | 23 | client.UpdateApiKey(newApiKey); 24 | Assert.AreEqual(newApiKey, client.GetApiKey()); 25 | } 26 | 27 | [TestMethod()] 28 | public void GetTest() 29 | { 30 | var mockApiClientCore = new MockApiClientCore("dummy"); 31 | var client = ApiClientCoreWithCache.Create(mockApiClientCore, cacheHelper); 32 | ApiGetRequest request = new ApiGetRequest("dummy endpoint", new Dictionary()); 33 | Assert.AreEqual(MockApiClientCore.Response, client.Get(request, false, true)); 34 | // use cache 35 | Assert.AreEqual(MockApiClientCore.Response, client.Get(request, false, true)); 36 | 37 | // don't use cache 38 | Assert.AreEqual(MockApiClientCore.Response, client.Get(request, false, false)); 39 | } 40 | 41 | [TestMethod()] 42 | public void GetExceptionTest() 43 | { 44 | var mockApiClientCore = new ErrorMockApiClientCore("dummy"); 45 | var client = ApiClientCoreWithCache.Create(mockApiClientCore, cacheHelper); 46 | ApiGetRequest request = new ApiGetRequest("dummy endpoint", new Dictionary()); 47 | Assert.ThrowsException(() => client.Get(request, false, false)); 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /BuffettCodeAddinRibbon/Settings/AddinSettings.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeCommon; 2 | using BuffettCodeCommon.Validator; 3 | 4 | namespace BuffettCodeAddinRibbon.Settings 5 | { 6 | public class AddinSettings 7 | { 8 | private readonly string apiKey; 9 | private readonly bool enabledOndemandEndpoint; 10 | private readonly bool debugMode; 11 | private readonly bool forceOndemandEndpoint; 12 | 13 | public string ApiKey => apiKey; 14 | public bool IsOndemandEndpointEnabled => enabledOndemandEndpoint; 15 | public bool DebugMode => debugMode; 16 | 17 | public bool IsForceOndemandEndpoint => forceOndemandEndpoint; 18 | 19 | private AddinSettings(string apiKey, bool useOndemandEndpoint, bool debugMode, bool forceOndemandEndpoint) 20 | { 21 | this.apiKey = apiKey; 22 | this.enabledOndemandEndpoint = useOndemandEndpoint; 23 | this.debugMode = debugMode; 24 | this.forceOndemandEndpoint = forceOndemandEndpoint; 25 | } 26 | 27 | public static AddinSettings Create(string apiKey, bool useOndemandEndpoint, bool debugMode, bool forceOndemandEndpoint) 28 | { 29 | ApiKeyValidator.Validate(apiKey); 30 | return new AddinSettings(apiKey, useOndemandEndpoint, debugMode, forceOndemandEndpoint); 31 | } 32 | 33 | public static AddinSettings Create(Configuration config) 34 | { 35 | return new AddinSettings(config.ApiKey, config.IsOndemandEndpointEnabled, config.DebugMode, config.IsForceOndemandApi); 36 | } 37 | 38 | public void SaveToConfiguration(Configuration config) 39 | { 40 | config.ApiKey = apiKey; 41 | // if ondemand endpoint is disabled, set force ondemand as false 42 | if (enabledOndemandEndpoint) 43 | { 44 | config.IsOndemandEndpointEnabled = true; 45 | config.IsForceOndemandApi = forceOndemandEndpoint; 46 | } 47 | else 48 | { 49 | config.IsForceOndemandApi = false; 50 | config.IsOndemandEndpointEnabled = false; 51 | } 52 | config.DebugMode = debugMode; 53 | } 54 | 55 | 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /BuffettCodeIOTests/Formatter/PropertyFormatterFactoryTests.cs: -------------------------------------------------------------------------------- 1 | using BuffettCodeIO.Property; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | namespace BuffettCodeIO.Formatter.Tests 5 | { 6 | [TestClass()] 7 | public class PropertyFormatterFactoryTests 8 | { 9 | [TestMethod] 10 | public void TestCreate() 11 | { 12 | IPropertyFormatter formatter; 13 | 14 | // 通貨 15 | formatter = CreateFormatter("dividend", "配当金", "円"); 16 | Assert.IsTrue(formatter is NumericFormatter); 17 | formatter = CreateFormatter("assets", "総資産", "百万円"); 18 | Assert.IsTrue(formatter is MillionYenFormatter); 19 | 20 | // 数値 21 | formatter = CreateFormatter("issued_share_num", "発行済株式総数", "株"); 22 | Assert.IsTrue(formatter is NumericFormatter); 23 | formatter = CreateFormatter("pbr", "PBR", "倍"); 24 | Assert.IsTrue(formatter is NumericFormatter); 25 | formatter = CreateFormatter("inventory_turnover", "棚卸資産回転期間", "日"); 26 | Assert.IsTrue(formatter is NumericFormatter); 27 | formatter = CreateFormatter("debt_monthly_sales_ratio", "有利子負債/月商比率", "ヶ月"); 28 | Assert.IsTrue(formatter is NumericFormatter); 29 | formatter = CreateFormatter("employee_num", "従業員数", "人"); 30 | Assert.IsTrue(formatter is NumericFormatter); 31 | 32 | // 割合 33 | formatter = CreateFormatter("tangible_fixed_assets_turnover", "有形固定資産回転率", "%"); 34 | Assert.IsTrue(formatter is RatioFormatter); 35 | 36 | // その他 37 | formatter = CreateFormatter("company_name", "社名", "なし"); 38 | Assert.IsTrue(formatter is InactionFormatter); 39 | 40 | // プロパティの定義を渡さなかったら常にInactionFormatter 41 | formatter = PropertyFormatterFactory.Create(null); 42 | Assert.IsTrue(formatter is InactionFormatter); 43 | } 44 | 45 | private IPropertyFormatter CreateFormatter(string name, string label, string unit) 46 | { 47 | PropertyDescription description = new PropertyDescription(name, label, unit); 48 | return PropertyFormatterFactory.Create(description); 49 | } 50 | 51 | } 52 | } --------------------------------------------------------------------------------